Один из самых важных моментов для присваивания ссылок на объекты подкласса переменным суперкласса наступает тогда, когда конструкторы вызываются в иерархии классов. Как вам должно быть уже известно, в классе нередко определяется конструктор, принимающий объект своего класса в качестве параметра. Благодаря этому в классе может быть сконструирована копия его объекта. Этой особенностью можно выгодно воспользоваться в подклассах, производных от такого класса. В качестве примера рассмотрим очередные версии классов TwoDShape и Triangle. В оба класса добавлены конструкторы, принимающие объект своего класса в качестве параметра. 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; } // Построение одного объекта на основании другого объекта. TwoDShape(TwoDShape ob) { width = ob.width; height = ob.height; } // Методы доступа к переменным 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 { super; style = "null"; } // Конструктор класса Triangle. Triangle(String s, double w, double h) { super(w, h); // вызвать конструктор суперкласса style = s; } // Конструктор с одним аргументом для построения треугольника. Triangle(double х) { super(х); // вызвать конструктор суперкласса style = "isosceles"; } // построить один объект на основании другого объекта Triangle(Triangle ob) { // Передача ссылки на объект Triangle конструктору класса TwoDShape. super(ob); style = ob.style; } double area { return getWidth * getHeight / 2; } void showStyle { System.out.println("Triangle is " + style); } } class Shapes7 { public static void main(String args[]) { Triangle tl = new Triangle("right", 8.0, 12.0); // создать копию объекта tl Triangle t2 = new Triangle(tl); System.out.println("Info for tl: "); 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); } }
В приведенном выше примере программы объект t2 конструируется на основании объекта tl, и поэтому они идентичны. Результат выполнения данной программы выглядит следующим образом: Info for tl: 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
Обратите внимание на конструктор класса Triangle, код которого приведен ниже. // построить один объект на основании другого объекта Triangle(Triangle ob) { // Передача ссылки на объект Triangle конструктору класса TwoDShape. super(ob); style = ob.style; }
В качестве параметра данному конструктору передается объект Triangle, который затем с помощью вызова super передается конструктору TwoDShape, как показано ниже. // Построение одного объекта на основании другого объекта. TwoDShape(TwoDShape ob) { width = ob.width; height = ob.height; }
Следует заметить, что конструктор TwoDshape должен получить объект типа TwoDShape, но конструктор Triangle передает ему объект типа Triangle. Тем не менее никаких недоразумений не возникает. Ведь, как пояснялось ранее, переменная ссылки на суперкласс может ссылаться на объект производного от него подкласса. Следовательно, конструктору TwoDShape можно передать ссылку на экземпляр подкласса, производного от класса TwoDShape. Конструктор TwoDShape инициализирует лишь те части передаваемого ему объекта подкласса, которые являются членами класса TwoDShape, и поэтому не имеет значения, содержит ли этот объект дополнительные члены, добавленные в производных подклассах. Переопределение методов