где список_параметров обозначает параметры, необходимые для нормальной работы конструктора суперкласса. Вызов конструктора super () должен быть первым оператором в теле конструктора подкласса. Для того чтобы лучше понять особенности вызова super (), рассмотрим вариант класса TwoDShape из следующего примера программы, где определен конструктор, инициализирующий переменные экземпляра width и height: // Добавление конструкторов в класс TwoDShape. class TwoDShape { private double width; private double height; // Параметризированный конструктор объектов класса TwoDShape. TwoDShape(double w, double h) { width = w; height = h; } // Методы доступа к переменным экземпляра width и height. double getWidth() { return width; } double getHeight() { return height; } void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } void showDim() { System.out.println("Width and height are " + width + " and " + height); } } // Подкласс, производный от класса TwoDShape, // для представления треугольников, class Triangle extends TwoDShape { private String style; Triangle(String s, double w, double h) { // Использование оператора super () для вызова // конструктора класса TwoDShape. super(w, h); // вызвать конструктор суперкласса style = s; } double area() { return getWidth() * getHeight() / 2; } void showStyle() { System.out.println("Triangle is " + style); } } class Shapes4 { public static void main(String args[]) { Triangle tl = new Triangle("isosceles", 4.0, 4.0); Triangle t2 = new Triangle("right", 8.0, 12.0); System.out.println("Info for tclass="underline" ") ; tl.showStyle(); tl.showDim(); System.out.println ("Area is " + tl.areaO); System.out.println(); System.out.println("Info for t2: ") ; t2.showStyle(); t2.showDim(); System.out.println("Area is " + t2.area()); } }
В конструкторе Triangle присутствует вызов конструктора super () с параметрами w и h. В результате управление получает конструктор TwoDShape (), инициализирующий переменные width и height значениями, передаваемыми ему в качестве параметров. Теперь класс Triangle уже не занимается инициализацией элементов суперкласса. Он должен инициализировать только собственную переменную экземпляра style. Конструктору TwoDShape () предоставляется возможность построить соответствующий подобъект так, как требуется для данного класса. Более того, в суперклассе TwoDShape можно реализовать функции, о которых не будут знать его подклассы. Благодаря этому код становится более устойчивым к ошибкам.
Любая форма конструктора, определенного в суперклассе, может быть вызвана с помощью оператора super (). Для выполнения выбирается тот вариант конструктора, который соответствует указываемым аргументам. В качестве примера ниже приведена расширенная версия классов TwoDShape и Triangle, содержащих конструкторы по умолчанию и конструкторы, принимающие один или более аргумент. // Добавление дополнительных конструкторов в класс TwoDShape. class TwoDShape { private double width; private double height; // Конструктор по умолчанию. TwoDShape() { width = height = 0.0; } // Параметризированный конструктор. TwoDShape(double w, double h) { width = w; height = h; } // Конструирование объекта с одинаковыми значениями // переменных экземпляра width и height. TwoDShape(double х) { width = height = x; } // Методы доступа к переменным экземпляра width и height. double getWidth() { return width; } double getHeight() { return height; } void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } void showDim() { System.out.println("Width and height are " + width + " and " + height); } } // Подкласс, производный от класса TwoDShape,. // для представления треугольников, class Triangle extends TwoDShape { private String style; // Использование оператора super () для вызова // разных вариантов конструктора TwoDShape() . // Конструктор по умолчанию. Triangle() { super(); // вызвать конструктор суперкласса по умолчанию style = "null"; } // Параметризированный конструктор. Triangle(String s, double w, double h) { super(w, h); // вызвать конструктор суперкласса с двумя аргументами style = s; } // Конструктор с одним аргументом. Triangle(double х) { super(х); // вызвать конструктор суперкласса с одним аргументом style = "isosceles" } double area() { return getWidth() * getHeight() / 2; } void showStyle() { System.out.println("Triangle is " + style); } } class Shapes5 { public static void main(String args[]) { Triangle tl = new Triangle(); Triangle t2 = new Triangle("right", 8.0, 12.0); Triangle t3 = new Triangle(4.0); tl = t2; System.out.println("Info for tclass="underline" "); tl.showStyle(); tl.showDim(); System.out.println ("Area is " + tl.areaO); System.out.println() ; System.out.println("Info for t2: "); t2.showStyle(); t2.showDim(); System.out.println("Area is " + t2.area()); System.out.println(); System.out.println("Info for t3: "); t3.showStyle(); t3.showDim(); System.out.println("Area is " + t3.area()); System.out.println(); } }
Выполнение этой версии программы дает следующий результат: Info for tclass="underline" Triangle is right Width and height are 8.0 and 12.0 Area is 48.0 Info for t2: Triangle is right Width and height are 8.0 and 12.0 Area is 48.0 Info for t3: Triangle is isosceles Width and height are 4.0 and 4.0 Area is 8.0
Еще раз напомним основные свойства вызова конструктора super (). Когда этот вызов присутствует в конструкторе подкласса, происходит обращение к конструктору его непосредственного суперкласса. Таким образом, вызывается конструктор того класса, который непосредственно породил вызывающий класс. Это справедливо и при многоуровневой иерархии. Кроме того, вызов конструктора super () должен быть первым оператором в теле конструктора подкласса. Применение ключевого слова super для доступа к членам суперкласса
Существует еще одна общая форма ключевого слова super, которая применяется подобно ключевому слову this, но ссылается на суперкласс данного класса. Эта общая форма обращения к члену суперкласса имеет следующий вид: super.член_класса
где член_класса обозначает метод или переменную экземпляра.
Данная форма ключевого слова super применяется в тех случаях, если член подкласса скрывает член суперкласса. Рассмотрим следующий пример несложной иерархии классов: // Применение ключевого слова super для предотвращения сокрытия имен. class А { int i; } // создать подкласс, расширяющий класс А. class В extends А { int i; // Эта переменная i скрывает переменную i из класса А. В (int a, int b) { // Оператор super.i ссылается на переменную i из класса А. super.i = а; // переменная i из класса А i = b; // переменная i из класса В } void show() { System, out .println ("i in superclass: 11 + super, i); System.out.println("i in subclass: " + i); } } class UseSuper { public static void main(String args[]) { В subOb = new В (1, 2)*; subOb.show(); } }
Результат выполнения данной программы выглядит следующим образом: i in superclass: 1 i in subclass: 2
Несмотря на то что переменная экземпляра i в классе В скрывает одноименную переменную в классе А, ключевое слово super позволяет обращаться к переменной i из суперкласса. Аналогичным образом ключевое слово super можно использовать для вызова методов суперкласса, скрываемых методами подкласса.
Пример для опробования 7.1. Расширение класса Vehicle
Для того чтобы продемонстрировать возможности наследования, расширим класс Vehicle, созданный в главе 4. Напомним, что класс Vehicle инкапсулирует данные о транспортных средствах и, в частности, сведения о количестве пассажиров, объеме топливного бака и потреблении топлива. Воспользуемся классом Vehicle в качестве заготовки для создания более специализированных классов. Например, транспортным средством, помимо прочих, является грузовик. Одной из важных характеристик грузовика является его грузоподъемность. Поэтому для создания класса Truck можно расширить класс Vehicle, добавив переменную экземпляра, хранящую сведения о допустимом весе перевозимого груза. В этом проекте переменные экземпляра будут объявлены в классе Vehicle как закрытые (private), а для обращения к ним будут созданы специальные методы доступа.
Последовательность действий
Создайте новый файл TruckDemo.java и скопируйте в него исходный код последней версии класса Vehicle, разработанной в главе 4.
Создайте класс Truck, исходный код которого приведен ниже. // Расширение класса Vehicle для грузовиков, class Truck extends Vehicle { private int cargocap; // грузоподъемность в фунтах // Конструктор класса Truck. Truck(int p, int f, int m, int c) { /* Инициализация переменных из класса Vehicle с помощью вызываемого конструктора этого класса. */ super(р, f, m); cargocap = с; } // Методы доступа к переменной cargocap. int getCargo() { return cargocap; } void putCargo(int c) { cargocap = c; } }