Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Герберт Шилдт. Java 2, v5.0 (Tiger). Новые возм...doc
Скачиваний:
5
Добавлен:
01.03.2025
Размер:
1.21 Mб
Скачать

Иерархии настраиваемых классов

Настраиваемые классы могут входить в состав иерархии классов точно так же, как и ненастраиваемые классы. Следовательно, настраиваемый класс может функционировать как суперкласс или быть производным классом (подклассом). Ключевое различие между иерархиями настраиваемых и не-настраиваемых классов состоит в том, что в иерархии настраиваемых классов любые аргументы типа, необходимые суперклассу, должны передаваться на верхние уровни иерархии всем производным классам. Этот механизм аналогичен передаче аргументов конструктора на все уровни иерархии.

Использование настраиваемого суперкласса

В листинге 3.12 приведен простой пример иерархии, в которой применяется настраиваемый суперкласс.

Листинг 3.12. Пример простой иерархии с применением настраиваемого класса

class Gen<T> {

T ob;

Gen(T o) {

ob = o;

}

// Return ob.

T getob() {

return ob;

}

}

// A subclass of Gen.

class Gen2<T> extends Gen<T> {

Gen2(T o) {

super(o);

}

}

В иерархии из листинга 3.12 класс Gen2 является расширением класса Gen. Рассмотрим приведенное в следующей строке объявление этого класса:

class Gen2<T> extends Gen<T> {

Параметр типа т задан в классе Gen2 и передается в класс Gen с помощью ключевого слова extends. Это означает, что при любой передаче типа классу Gen2 этот же параметр будет передан классу Gen. Например, следующее объявление:

Gen2<Integer> num = new Gen2<Integer>(100);

передает класс Integer как параметр типа классу Gen. Следовательно, объект ob в составляющей класса Gen2, унаследованной от класса Gen, будет

иметь тип Integer.

Обратите внимание также на то, что параметр типа T в классе Gen2 используется только для передачи его в суперкласс Gen. Таким образом, даже если нет необходимости формировать настраиваемый подкласс от настраиваемого суперкласса, в нем все равно нужно определить параметр (или параметры) типа, требующиеся для его настраиваемого суперкласса.

Конечно, в производный класс при необходимости можно добавить его собственные параметры типа. В листинге 3.13 приведен вариант иерархии из листинга 3.12, в которой в класс Gen2 включен его собственный параметр типа.

Листинг 3.13. Пример подкласса с собственным параметром типа

class Gen<T> {

T ob; // declare an Object of type T

// Pass the constructor a reference to

// an Object of type T.

Gen(T o) {

ob = o;

}

// Return ob.

T getob() {

return ob;

}

}

// A subclass of Gen that defines a second

// type parameter, called V.

class Gen2<T, V> extends Gen<T> {

V ob2;

Gen2(T o, V o2) {

super(o);

ob2 = o2;

}

V getob2() {

return ob2;

}

}

// Create an Object of type Gen2.

class HierDemo {

public static void main(String args[]) {

// Create a Gen2 Object for String and Integer.

Gen2<String, Integer> x =

new Gen2<String, Integer>("Value is: ", 99);

System.out.print(x.getob());

System.out.println(x.getob2());

}

}

Рассмотрим объявление версии класса Gen2 в приведенной далее строке:

class Gen2<T, V> extends Gen<T> {

Здесь T — параметр типа, передаваемый в класс Gen, a V — параметр типа, специфичный для класса Gen2. Параметр v используется для объявления объекта ob2 и определения типа данных, возвращаемых методом getob2(). В методе main () создается объект класса Gen2, в котором тип T заменен классом String, а параметр V — классом Integer. Результат работы программы приведен в следующей строке:

Value is: 99