Главная страница

Лабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74


Скачать 1.76 Mb.
НазваниеЛабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74
Дата12.03.2021
Размер1.76 Mb.
Формат файлаdoc
Имя файлаOOP_Lab_Rus.doc
ТипЛабораторная работа
#184105
страница20 из 31
1   ...   16   17   18   19   20   21   22   23   ...   31

5.10 Ссылка для суперкласса.


Ссылочной переменной суперкласса может быть назначена ссылка на любой подкласс, производный от того суперкласса. Вы найдете этот аспект наследования весьма полезным в ряде ситуаций. Рассмотрим следующий пример:
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("Bec 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);

}

}
Здесь eightbox – ссылка на объекты BoxWeight, a plainbox – ссылка на Box-объекты. Так как BoxWeight – подкласс Box, допустимо назначить piainbox-ссылку на объект weightbox.

Важно понять, что тип ссылочной переменной, а не тип объекта, на который она ссылается, определяет, к каким членам можно обращаться. То есть, когда ссылка на объект подкласса указывает на ссылочную переменную суперкласса, вы будете иметь доступ только к тем частям объекта, которые определены суперклассом. Вот почему plainbox не может ссылаться на weight, даже когда она ссылается на Boxweight-объект. Если подумать, то данное взаимодействие оправдано, потому что суперкласс не знает, что к нему добавляет подкласс. Вот почему последняя строка кода в предшествующем фрагменте закомментирована. У ссылки нет возможности обратиться к полю weight, потому что в Box оно не определено.

5.11 Использование ключевого слова super


В предшествующих примерах классы, производные от Box, не были реализованы так эффективно или устойчиво, как это могло бы быть. Например, конструктор класса BoxWeight явно инициализирует поля width, height и depth метода Box(). Мало того, что он дублирует код своего суперкласса, что неэффективно, но это означает, что подклассу должен быть предоставлен доступ к этим членам. Однако наступит момент, когда вы захотите создать суперкласс, который сохраняет подробности своей реализации для себя (т.е. хранит свои компоненты данных как private). В этом случае у подкласса не будет никакой возможности прямого доступа или инициализации этих переменных как своих собственных. Так как инкапсуляция это первичный атрибут ООП, не удивительно, что Java обеспечивает решение этой проблемы. Всякий раз, когда подкласс должен обратиться к своему непосредственному суперклассу, он может сделать это при помощи ключевого слова super.

Ключевое слово super имеет две общие формы. Первая вызывает конструктор суперкласса. Вторая используется для доступа к элементу суперкласса, который был скрыт элементом подкласса.
1. Подкласс может вызывать метод конструктора, определенный его суперклассом, при помощи следующей формы super:
super(parameter-list);
Здесь parameter-list – список параметров, который определяет любые параметры, необходимые конструктору в суперклассе. Похожий по форме на конструктор super() должен всегда быть первым оператором, выполняемым внутри конструктора подкласса.

Чтобы посмотреть, как super() используется, приведем следующую улучшенную версию класса BoxWeight.
// BoxWeight теперь использует super для инициализации Box-атрибутов.

class BoxWeight extends Box {

double weight; // вес блока
// инициализировать width, height и depth, используя super()

BoxWeight(double w, double h, double d, double m) {

super(w, h, d); // вызвать конструктор суперкласса

weight = m;

}

}
Здесь BoxWeight() вызывает super() с параметрами w, h и d. Используя эти параметры, super о вызывает конструктор Вох(), который инициализирует width, height и depth. BoxWeight больше не инициализирует эти значения самостоятельно. Он нуждается в инициализации только уникальной для него переменной – weight. Box, если пожелает, может закрыть свои переменные (сделать их private).

В предыдущем примере, super() вызывался с тремя параметрами. Так как конструкторы могут быть перегружены, super() может вызывать любую их форму, определенную в суперклассе. Выполняться будет тот конструктор, который соответствует аргументам super о. Например, имеется законченная реализация BoxWeight, которая обеспечивает конструкторы для различных способов создания блока. В каждом случае вызывается super(), использующий соответствующие параметры. Обратите внимание, что width, height и depth объявлены частными (private) в классе Box.
// Полная реализация BoxWeight.

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;

}

}
// BoxWeight теперь полностью реализует все конструкторы.

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 DemoSuper {

public static void main(String args[]) {

BoxWeight myboxl = new BoxWeight(10, 20, 15, 34.3);

BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);

BoxWeight mybox3 = new BoxWeight(); //по умолчанию

BoxWeight mycube = new BoxWeight(3, 2);

BoxWeight myclone = new BoxWeight(myboxl);

double vol;
vol = myboxl.volume();

System.out.println("Объем myboxl равен " + vol);

System.out.println("Вес myboxl равен " + myboxl.weight);

System.out.println();
vol = mybox2.volume();

System.out.println("Объем mybox2 равен " + vol);

System.out.println("Вес mybox2 равен " + mybox2.weight);

System.out.println();
vol = mybox3.volume();

System.out.println("Объем mуbоx3 равен " + vol);

System.out.println("Вес mybox3 равен " + mybox3.weight);

System.out.println();
vol = myclone.volume();

System.out.println("Объем myclone равен " + vol);

System.out.println("Вес myclone равен " + myclone.weight);

System.out.println();
vol = mycube.volume();

System.out.println("Объем mycube равен " + vol);

System.out.println("Вес mycube равен " + mycube.weight);

System.out.println();

}

}
Эта программа генерирует следующий вывод:
Объем myboxl равен 3000.0

Вес myboxl равен 34.3
Объем mybox2 равен 24.0

Вес mybox2 равен 0.076
Объем mуbоx3 равен -1.0

Вес mybox3 равен -1.0
Объем myclone равен 3000.0

Вес myclone равен 34.3
Объем mycube равен 27.0

Вес mycube равен 2.0
Обратите особое внимание на следующий конструктор в BoxWeight():
// построить клон объекта

BoxWeight(BoxWeight ob) { // передать объект конструктору

super (ob);

weight = ob.weight;

}
super() вызывается с объектом типа BoxWeight – не типа Box. Но вызывается при этом все еще конструктор Box(Box ob). Переменная суперкласса может использоваться для ссылки на любой производный объект этого класса. Таким образом, мы способны передать объект BoxWeight конструктору Box. Но, конечно, только Box «знает» свои собственные члены.

Сделаем обзор ключевых концепций super(). Когда подкласс вызывает super(), он вызывает конструктор своего непосредственного суперкласса. Таким образом, super() всегда обращается к непосредственному суперклассу вызывающего класса. Это справедливо даже в многоуровневой иерархии. Кроме того, super() всегда должен быть первым оператором, выполняемым внутри конструктора подкласса.
2. Вторая форма super действует в чем-то подобно ссылке this, за исключением того, что она всегда обращается к суперклассу подкласса, в котором используется. Общий формат такого использования super имеет вид:
super.member
где member может быть либо методом, либо переменной экземпляра.

Вторая форма super больше всего применима к ситуациям, когда имена элементов (членов) подкласса скрывают элементы с тем же именем в суперклассе. Рассмотрим следующую простую иерархию классов:
// Использование super для преодоления скрытия имен.

class A {

int i;

}
// Создание подкласса B расширением класса A.

class B extends A {

int i; // этот i скрывает i в A

B(int a, int b) {

super.i = a; // i из A

i = b; // i из B

}
void show() {

System.out.println("i из суперкласса: " + super.i);

System.out.println("i из подкласса: " + i);

}

}
class UseSuper {

public static void main(String args[]) {

B subOb = new B(1, 2);

subOb.show();

}

}
Эта программа выполняет следующий вывод:
i из суперкласса: 1

i из подкласса: 2
Хотя экземплярная переменная i класса B скрывает i класса A, super позволяет получить доступ к i, определенной в суперклассе. Кроме того, super можно также использовать для вызова методов, скрытых подклассом.
1   ...   16   17   18   19   20   21   22   23   ...   31


написать администратору сайта