Как можно было сделать существующие классы Java подклассами AnyRef в Scala? - PullRequest
0 голосов
/ 01 мая 2018

Диаграмма иерархии наследования Scala:

Диаграмма выше из книги Scala для нетерпеливых показывает, что все классы Java являются подклассами класса AnyRef.

На рисунке 8–1 показана иерархия наследования классов Scala. Классы, которые соответствуют примитивным типам в Java, а также типу Unit, расширяют AnyVal. Все остальные классы являются подклассами класса AnyRef, который является синонимом класса Object из виртуальной машины Java или .NET. И AnyVal, и AnyRef расширяют класс Any, корень иерархии.

Как это было достигнуто без изменения классов Java? Об этом заботятся на уровне байт-кода?

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Это то, что часто смущает начинающих. Недавно был очень похожий вопрос о Software Engineering.SE . Ответ прост: МАГИЯ!

Да, действительно.

Компилятор Scala не обязан соблюдать правила языка Scala. В некотором смысле, это является правилами языка Scala! Он должен реализовывать и применять их, но не должен следовать им. И это, безусловно, не должно следовать правилам языка Java.

Таким образом, способ, которым это происходит, действительно прост: всякий раз, когда какая-то программа Scala делает что-то, что зависит от поведения java.lang.String, как если бы это был подкласс scala.AnyRef, она генерирует код, который ведет себя так, как если бы java.lang.String было подкласс scala.AnyRef.

Вот и все.

Вы также можете спросить, как Scala создает объекты примитивов Java, которые являются экземплярами классов, которые являются подклассами scala.AnyVal. Или вы можете спросить, как вы, программист, можете видеть частные реализации двух классов, когда открываете исходный код двух файлов в двух окнах редактора, даже если язык говорит, что вы не можете видеть частные реализации извне.

Причина всегда одна и та же: поскольку вы сидите вне языка, языковые правила к вам не относятся.

С другой стороны, люди часто спрашивают, почему они могут создавать подклассы sealed классов из Java или вызывать методы, объявленные как private[this]. Причина снова та же: потому что компилятор Java не должен играть по правилам Scala. Он даже не знает о правилах Скалы.

0 голосов
/ 01 мая 2018

Отказ от ответственности: я ни в коем случае не эксперт по Scala, но у меня 20-летний опыт работы с Java, включая JVM.

Моя интерпретация заключается в том, что предложение

Все остальные классы являются подклассами класса AnyRef, который является синоним для класса Object из виртуальной машины Java или .NET.

(выделено мной) объясняет это прекрасно.

Для JVM нет класса AnyRef. Текст называет AnyRef синонимом, и у JVM такого понятия нет. Так что, вероятно, компилятор Scala заменяет вхождения AnyRef на java.lang.Object. И, конечно, все классы Java являются подклассами java.lang.Object, которые только что получили новое имя в компиляторе Scala, что делает их все наследуемыми от AnyRef (a.k.a. Object)

Могу поспорить, что вы не найдете запись AnyRef.class в какой-либо библиотеке JAR времени выполнения Scala, что означает, что для JVM такого класса, как AnyRef, не существует.

...