Используя типы, вы по существу даете подсказки компилятору для проверки вашего кода.Поэтому, сказав val crystal: Crystal = salt
, вы просто скажете ему, чтобы с этого момента crystal
считался менее специфичным классом Crystal
(т. Е. Формально проверяйте свой код только с учетом этого).
В этом случае вы не изменяете фактический объект (тем более, что вы не можете иметь экземпляры абстрактного класса, которым является Crystal
).Поэтому, если вы скажете crystal.grow()
, интерпретатор все равно будет искать наиболее конкретную версию grow()
, которую он сможет найти, в данном случае переопределенную в Salt
.Вы можете проверить это с помощью getClass
:
scala> salt.getClass
res1: Class[_ <: Salt] = class Salt
scala> crystal.getClass
res2: Class[_ <: Crystal] = class Salt
Что касается того, почему crystal
и salt
указывают на один и тот же объект.Scala / Java делает копии только для примитивных типов (например, Int или Double; как и во многих других языках), т. Е. Для объектов мы просто создаем указатель на тот же объект.