До этого момента мы использовали простые иерархии классов, которые состоят только из суперкласса и подкласса. Однако можно строить иерархии, которые содержат столько уровней наследования, сколько вам нравится. Как уже говорилось, вполне приемлемо использовать подкласс в качестве суперкласса другого класса. Например, при наличии трех классов с именами А, B и C, класс С может быть подклассом B, который, в свою очередь, является подклассом А. В этом случае каждый подкласс наследует все черты всех своих суперклассов. В данном случае C наследует все аспекты B и A. Чтобы продемонстрировать пользу многоуровневой иерархии, рассмотрим следующую программу:
// Расширить BoxWeight для включения стоимости отгрузки.
// Начать с класса Box.
class Box {
private double width;
private double height;
private double depth;
// создать клон объекта
Box(Box ob) { // передать объект конструктору
width = ob.width;
height = ob.height;
depth = ob.depth;
}
// конструктор, использующий все размеры
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// конструктор, не использующий размеров
Box() {
width = -1; // использовать -1 для указания
height = -1; // неинициализированного
depth = -1; // блока
}
// конструктор для создания куба
Box(double len) {
width = height = depth = len;
}
// вычислить и возвратить объем
double volume() {
return width * height * depth;
}
}
// Добавить вес.
class BoxWeight extends Box {
double weight; // вес блока
// создать клон объекта
BoxWeight(BoxWeight ob) { // передать объект конструктору
super(ob);
weight = ob.weight;
}
// конструктор, использующий все специфицированные параметры
BoxWeight(double w, double h, double d, double m) {
Здесь подкласс Boxweight используется как суперкласс для создания подкласса с именем Shipment. Shipment наследует все черты BoxWeight и Box и добавляет поле с именем cost (стоимость), которое содержит стоимость отгрузки такого пакета.
Вывод этой программы:
Объем shipmentl равен 3000.0
Вес shipmentl равен 10.0
Стоимость отгрузки: $3.41
Объем shipment2 равен 24.0
Вес shipment2 равен 0.76
Стоимость отгрузки: $1.28
Из-за наследования shipment может использовать предварительно определенные классы Box и BoxWeight, добавляя только дополнительную информацию, которая требуется для своего собственного специфического применения. Одно из преимуществ наследования – возможность повторного использования кода.
Этот пример иллюстрирует другой важный аспект: super() всегда обращается к конструктору в самом близком суперклассе, super() в Shipment вызывает конструктор класса BoxWeight. super() в BoxWeight вызывает конструктор класса Bох. В иерархии классов, если конструктор суперкласса требует наличие параметров, то все подклассы должны передать эти параметры «вверх по линии». И это не зависит от того, нуждается ли подкласс в своих собственных параметрах.
Замечание. В предыдущей программе полная иерархия классов, включающая Box, BoxWeight и Shipment, показана вся в одном файле. Это только для вашего удобства. В Java все три класса были бы помещены в свои собственные файлы и откомпилированы отдельно. При создании иерархий классов использование отдельных файлов на самом деле – норма, а не исключение.