Почему значение класса scala #toString содержит информацию о классе дела?

Классы значений могут использоваться для обеспечения безопасности типов без дополнительных затрат на распаковку.

У меня сложилось впечатление, что во время выполнения такие типы / классы "не существовали бы", рассматриваясь как простые типы (например, класс значений). case class X(i: Int) extends AnyVal было бы просто Int во время выполнения).

Но если вы позвоните .toString Метод на экземпляре класса значения будет печатать что-то вроде:

scala> val myValueClass = X(3)
myValueClass: X = 3

scala> myValueClass.toString
res5: String = X(3)

так что я предполагаю, что компилятор включает некоторую информацию в конце концов?

2 ответа

Решение

На самом деле, нет. Компилятор создает статический метод (в Scala это соответствует объекту-компаньону класса), который вызывается с вашим значением int в качестве параметра, чтобы имитировать вызов метода для вашего объекта типа value.

Ваш класс значений сам существует только в исходном коде. В скомпилированном байт-коде используется фактический примитив int и вызываются статические методы, а не новые экземпляры объектов с реальными вызовами методов. Вы можете прочитать больше об этом механизме здесь.

Классы значений разработаны так, чтобы добавление или удаление extends AnyVal (если допустимо) не должен изменять результаты вычислений (за исключением того, что классы, не относящиеся к регистру equals а также hashCode определяется автоматически, как классы дел). Это требует, чтобы при некоторых обстоятельствах они выжили, например,

def toString(x: Any) = x.toString

toString(myValueClass)

но ситуация в вашем вопросе не одна из них.

http://docs.scala-lang.org/sips/completed/value-classes.html более точно объясняет, как реализуются классы значений, и полезно посмотреть, в каких случаях они выживают, хотя некоторые детали могли измениться с тех пор.

Другие вопросы по тегам