При создании объекта:
BaseClass b1 = new DerievedClass();
То, что мы говорим:
ReferenceType variableName = new ConcreteImplementation();
Думайте об этом как о ReferenceType, обеспечивающем основу для нового Объекта.
Когда объект создается, он обращается к этому ReferenceType и создает объект со всеми методами в ReferenceType как скелет.
Затем мы смотрим на ConcreteImplementation для реализации методов.
Поэтому компилятор обращается к ConcreteImplementation, чтобы заполнить все методы.
В конечном объекте реализовано только то, что определено в ReferenceType.
Думайте о приведении как об изменении ReferenceType уже существующего объекта
со строкой:
DerievedClass d = new DerievedClass();
ReferenceType - это DeriveClass, поэтому мы берем все методы из DerivedClass
и заполните их реализацией из ConcreteImplementation, которая является DerivedClass.
Затем мы приводим DeriveClass d к BaseClass b.
BaseClass b = BaseClass.class.cast(d);
d имеет всю реализацию из DerivedClass, но скаффолд получен из базового класса ReferencType, поэтому мы не можем вызвать printMagic
потому что он не существует в BaseClass.
Имеет ли это смысл?
Надеюсь, это поможет