Почему значение класса 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 более точно объясняет, как реализуются классы значений, и полезно посмотреть, в каких случаях они выживают, хотя некоторые детали могли измениться с тех пор.