Ссылочной переменной суперкласса может быть присвоена ссылка на любой подкласс, производный от данного суперкласса. Этот аспект наследования будет весьма полезен во множестве ситуаций. Рассмотрим следующий пример:
class RefDemo {
public static void main(String args[]) {
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37);
Box plainbox = new Box() ;
double vol;
vol = weightbox.volume();
System.out.println("Объем weightbox равен " + vol);
System.out.println("Bee weightbox равен " +
weightbox.weight);
System.out.println();
// присваивание объекту BoxWeight ссылки на ссылку объекта
Box plainbox = weightbox;
vol = plainbox.volume (); // OK, метод volume О определен в Box
System.out.println("Объем plainbox равен " + vol);
/* Следующий оператор ошибочен, поскольку plainbox не определяет член weight. */
// System.out.println("Вес plainbox равен " + plainbox.weight);
}
}
В этом примере weightbox — ссылка на объекты BoxWeight, a painbox — ссылка на объекты Box. Поскольку BoxWeight — подкласс класса Box, ссылке painbox можно присваивать ссылку на объект weightbox.
Важно понимать, что доступные объекты определяются типом ссылочной переменной, а не типом объекта, на который она ссылается. То есть при присваивании ссылочной переменной суперкласса ссылки на объект подкласса доступ предоставляется только к указанным в ней частям объекта, определенного суперклассом. Именно поэтому объект plainbox не имеет доступа к переменной weight даже в том случае, когда он ссылается на объект BoxWeight. Если немного подумать, это становится понятным — суперклассу не известно, что именно подкласс добавляет в него. Поэтому последняя строка кода в предыдущем фрагменте оформлена в виде комментария. Ссылка объекта Box не имеет доступа к полю weight, поскольку оно не определено в классе Box.
Хотя все сказанное выше может казаться несколько запутанным, эти особенности находят ряд практических применений, два из которых рассматриваются в последующих разделах данной главы.