До сих пор мы использовали простые иерархии классов, которые состояли
только из суперкласса и подкласса. Однако можно строить иерархии, которые содержат любое количество уровней наследования.
Скачать исходники для статьи можно ниже
Как уже отмечалось, вполне допустимо использовать подкласс в качестве суперкласса другого подкласса.
Например, класс С может быть подклассом класса В, который, в свою очередь, является подклассом класса А.
В подобных ситуациях каждый подкласс наследует все характеристики всех его суперклассов.
В приведенном примере класс С наследует все характеристики классов В и А.
В качестве примера многоуровневой иерархии рассмотрим следующую программу. В ней подкласс BoxWeight использован в качестве суперкласса для создания подкласса Shipment. Класс Shipment наследует
все характеристики классов BoxWeight и Box, а также добавляет поле cost, которое содержит стоимость поставки такого пакета.
// Расширение класса 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) { super(w, h, d); // вызов конструктора суперкласса weight = m; } // конструктор, используемый по умолчанию BoxWeight() { super(); weight = -1; } // конструктор, используемый при создании куба BoxWeight(double len, double m) { super(len); weight = m; } } // Добавление стоимости доставки class Shipment extends BoxWeight { double cost; // конструирование клона объекта Shipment(Shipment ob) { // передача объекта конструктору super(ob); cost = ob.cost; } // конструктор, используемый при указании всех параметров Shipment(double w, double h, double d, double m, double c){ super(w, h, d, m); // вызов конструктора суперкласса cost = с; } // конструктор, используемый по умолчанию Shipment() { super(); cost = -1; } // конструктор, используемый при создании куба Shipment(double len, double m, double c) { super(len, m); cost = c; } } class DemoShipment { public static void main(String args[]) { Shipment shipment1 = new Shipment(10, 20, 15, 10, 3.41); Shipment shipment2 = new Shipment(2, 3, 4, 0.76, 1.28); double vol; vol = shipment1.volume(); System.out.println("Объем shipmentl равен " + vol); System.out.println("Bec shipmentl равен " + shipment1.weight); System.out.println("Стоимость доставки: $" + shipment1.cost); System.out.println(); vol = shipment2.volume(); System.out.println("Объем shipment2 равен " + vol); System.out.println("Bec shipment2 равен " + shipment2.weight); System.out.println("Стоимость доставки: $" + shipment2.cost); } }
Вывод этой программы будет следующим:
Объем shipment1 равен 3000.0
Вес shipmentl равен 10.0
Стоимость доставки: $3.41
Объем shipment2 равен 24.0
Вес shipment2 равен 0.76
Стоимость доставки: $1.28
Благодаря наследованию, класс Shipment может использовать ранее определенные классы Box и BoxWeight, добавляя только ту дополнительную информацию, которая требуется для его собственного специализированного применения.
В этом состоит одно из ценных свойств наследования. Оно позволяет повторно использовать код.
Приведенный пример иллюстрирует важный аспект: метод super() всегда
ссылается на конструктор ближайшего суперкласса в иерархии.
Метод super() в классе Shipment вызывает конструктор класса BoxWeight. Метод super() в классе BoxWeight вызывает конструктор класса Box.
Если в иерархии классов конструктор суперкласса требует передачи ему параметров, все подклассы должны передавать эти параметры “по эстафете”. Данное утверждение справедливо независимо от того, нуждается ли подкласс в собственных параметрах.