Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
41
Добавлен:
12.05.2015
Размер:
624.64 Кб
Скачать

Когда вызываются конструкторы

Когда иерархия классов создана, в каком порядке вызываются конструкторы классов, образующих иерархию? Например, если имеется подкласс в и су­перкласс а, д-конструктор вызывается перед в-конструкторами, или наобо­рот? Ответ заключается в том, что в иерархии классов конструкторы вызы­ваются в порядке подчиненности классов – от суперкласса к подклассу. Далее, так как super о должен быть первым оператором, выполняемым в конструкторе подкласса, этот порядок всегда одинаков и не зависит от того, используется ли super (). Если -super о не используется, то сначала будет выполнен конструктор по умолчанию (без параметров) каждого суперкласса. Следующая программа иллюстрирует, когда выполняются конструкторы:

// Демонстрирует порядок вызова конструкторов.

// Создать суперкласс А.

class A { А() {

System.out.println("Внутри А-конструктора.");

}

}

// Создать подкласс В расширением А.

class В extends A {

ВО {

System.out.println("Внутри В-конструктора.");

}

}

// Создать другой класс (С), расширяющий В.

class С extends В {

СО {

System.out.println("Внутри С-конструктора.");

}

}

class CallingCons {

public static void main(String args[]) {

С с = new С();

}

}

Вывод этой программы:

Внутри А-конструктора.

Внутри В-конструктора.

Внутри С-конструктора.

Не трудно видеть, что конструкторы вызываются в порядке подчиненности классов.

Если подумать, то выполнение функций конструкторов в порядке подчи­ненности классов имеет определенный смысл. Поскольку суперкласс не имеет никакого знания о каком-либо подклассе, любая инициализация, ко­торую ему нужно выполнить, является отдельной и, по возможности, пред­шествующей любой инициализации, выполняемой подклассом. Поэтому-то она и должна выполняться первой.

Переопределение методов

В иерархии классов, если метод в подклассе имеет такое же имя и сигнатуру типов (type signature), как метод в его суперклассе, говорят, что метод в подклассе переопределяет (override) метод в суперклассе. Когда переопределен­ный метод вызывается в подклассе, он будет всегда обращаться к версии этого метода, определенной подклассом. Версия метода, определенная су­перклассом, будет скрыта. Рассмотрим следующий фрагмент:

// Переопределение методов.

class A {

int i, j;

A(int a, int b) {

i = a;

j = b;

}

// показать i и j на экране

void show() {

System.out.println)"! и j: " + i + " " + j);

}

}

class В extends A {

int k;

В(int a, int b, int c) {

super(a, b);

k = c;

}

// Показать на экране k (этот show() переопределяет show() из А)

void show() {

System.out.println("k: " + k) ;

}

}

class Override {

public static void main(String args[]) {

В subOb = new В (1, 2, 3) ;

subOb.show(); // здесь вызывается show() из В

}

}

Вывод этой программы:

k: 3

Когда show () вызывается для объекта типа в, используется версия show (), определенная в классе в. То есть версия show () внутри в переопределяет (отменяет) версию, объявленную в а.

Если нужно обратиться к версии суперкласса переопределенной функции, то можно сделать это, используя super. Например, в следующей версии подкласс в вызывается show о версия суперкласса а. Это позволяет отобразить все экземплярные переменные.

class В extends A {

int k;

B(int a, int b, int с) {

super(a, b);

k = c;

}

void show() {

super.show(); // вызов show() суперкласса А

System.out.println("k: " + k) ;

}

}

Если вы замените этой версией класс в предыдущей программы, то получи­те следующий вывод:

i и j : 1 2

k: 3

Здесь super, show о вызывает версию show о суперкласса.

Переопределение метода происходит только тогда, когда имена и сигнатуры типов этих двух методов идентичны. Если это не так, то оба метода просто перегружены. Например, рассмотрим следующую модифицированную вер­сию предыдущего примера:

// Методы с различными сигнатурами типов перегружаются, а не переопределяются,

class A {

int i, j;

A(int a, int b) {

i - a;

j = b; }

// Показать i и j void show(} {

System.out.println("i и j: " + i + " " + j);

}

}

// Создать подкласс В расширением класса А.

class B extends A {

int k;

B(int a, int b, int c) { . •

super(a, b) ;

k = c; }

// Перегруженный sliowf)

void show(String msg) {

System.out.println(msg + k) ;

}

}

class Override {

public static void main(String args[]) {

В subOb = new B(l, 2, 3);

subOb.show("Это k: "); // вызов show() класса В

subOb. show () ; // вызов show () класса А

}

}

Вывод этой программы:

Это k: 3

i и j : 1 2

Версия show о в классе в имеет строчный параметр. Это делает сигнатуру его типов отличной от класса а, который не имеет никаких параметров. Поэто­му никакого переопределения (или скрытия имени) нет.

Соседние файлы в папке JavaLit