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

Настраиваемые конструкторы

Конструкторы также могут быть настраиваемыми, даже если их класс не является настраиваемым типом. Рассмотрим короткую программу, приведенную в листинге 3.9.

Листинг 3.9. Применение настраиваемого конструктора

class GenCons {

private double val;

<T extends Number> GenCons(T arg) {

val = arg.doubleValue();

}

void showval() {

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

}

}

class GenConsDemo {

public static void main(String args[]) {

GenCons test = new GenCons(100);

GenCons test2 = new GenCons(123.5F);

test.showval();

test2.showval();

}

}

Далее приведен вывод программы из листинга 3.9:

val: 100.0

val: 123.5

Поскольку конструктор GenCons( ) задает параметр настраиваемого типа, который должен быть производным классом от класса Number, его можно вызвать c любым числовым типом, включая Integer, Float или Double.

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

Настраиваемые интерфейсы

Кроме настраиваемых классов и методов Вы можете создавать настраиваемые интерфейсы (generic interface). Они задаются так же, как настраиваемые классы. В листинге 3.10 приведен пример настраиваемого интерфейса. В нем создается интерфейс, названный MinMax, объявляющий методы min() и mах(), которые должны возвращать минимальное и максимальное значения некоторого множества объектов.

Листинг 3.10. Пример настраиваемого интерфейса

// Интерфейс Min/Max.

interface MinMax<T extends Comparable<T>> {

T min();

T max();

}

// Теперь реализуем MinMax

class MyClass<T extends Comparable<T>> implements MinMax<T> {

T[] vals;

MyClass(T[] o) { vals = o; }

// Возвращает минимальное значение из vals.

public T min() {

T v = vals[0];

for(int i=1; i < vals.length; i++)

if(vals[i].compareTo(v) < 0) v = vals[i];

return v;

}

// Возвращает максимальное значение из vals. public T max() {

T v = vals[0];

for(int i=1; i < vals.length; i++)

if(vals[i].compareTo(v) > 0) v = vals[i];

return v;

}

}

class GenIFDemo {

public static void main(String args[]) {

Integer inums[] = {3, 6, 2, 8, 6 };

Character chs[] = {'b', 'r', 'p', 'w' };

MyClass<Integer> iob = new MyClass<Integer>(inums);

MyClass<Character> cob = new MyClass<Character>(chs);

System.out.println("Max value in inums: " + iob.max());

System.out.println("Min value in inums: " + iob.min());

System.out.println("Max value in chs: " + cob.max());

System.out.println("Min value in chs: " + cob.min());

}

}

Далее приведен вывод результатов работы программы из листинга 3.10:

Max value in inums: 8

Min value in inums: 2

Max value in chs: w

Min value in chs: b

Несмотря на то, что большая часть кода листинга 3.10 понятна, следует сделать несколько замечаний. Во-первых, обратите внимание на объявление интерфейса MinMax, приведенное в следующей строке:

interface MinMax<T extends Comparable<T>> {

Вообще настраиваемый интерфейс объявляется так же, как настраиваемый класс. В нашем случае параметр типа — T, и он должен расширять тип comparable. Обратите внимание на то, что тип comparable — тоже настраиваемый тип. Он принимает параметр типа, который задает тип сравниваемых объектов.

Далее класс MyClass реализует интерфейс MinMax. Рассмотрим объявление класса MyClass, приведенное в следующей строке:

class MyClass<T extends Comparable<T>> implements MinMax<T> {

Уделите особое внимание способу, которым параметр типа т объявляется в классе MyClass и затем передается в интерфейс MinMax. Поскольку интерфейсу MinMax требуется тип, расширяющий тип comparable, в классе, реализующем интерфейс (в нашем случае MyClass), должна быть задана та же самая граница. Более того, как только эта граница установлена, нет необходимости задавать ее снова в той части объявления класса, которая начинается с ключевого слова implements, На самом деле подобное действие было бы ошибкой. Например, приведенная далее часть кода некорректна и не будет компилироваться.

// Это неправильно!

class MyClass<T extends Comparable<T>>

implements MinMax<T extends Comparable<T>> {

Уже заданный параметр типа просто передается в интерфейс без дальнейшей модификации.

Вообще, если класс реализует настраиваемый интерфейс, этот класс также должен быть настраиваемым, по крайней мере, до той степени, которая обеспечивает получение параметра типа и передачу его в интерфейс. Например, приведенная далее строка кода, в которой делается попытка объявить класс MyClass, ошибочна:

class MyClass implements MinMax<T> { //Ошибка!

Поскольку в классе MyClass не объявлен параметр типа, не существует способа передачи его в интерфейс MinMax. В данном случае идентификатор T просто неизвестен, и компилятор сообщит об этой ошибке. Конечно, если класс реализует конкретную версию настраиваемого интерфейса, такую как приведенная в следующей строке:

class MyClass implements MinMax<Integer> { // OK

реализующему классу нет необходимости быть настраиваемым.

Применение настраиваемого интерфейса обладает двумя преимуществами. Во-первых, интерфейс можно реализовать для данных разных типов. Во-вторых, у вас появляется возможность наложить ограничения (т. е. установить границы) на типы данных, для которых может быть реализован интерфейс. В случае интерфейса MinMax, например, только типы, реализующие интерфейс comparable, могут передаваться для замены параметра T.

Далее приведена обобщенная синтаксическая конструкция для описания настраиваемого интерфейса:

interface interface-name<type-param-list> {//...

В данной записи type-param-listэто разделенный запятыми список параметров типа. Когда настраиваемый интерфейс реализуется, Вы должны заменить его списком аргументов типа, как показано в следующей строке:

class class-name<type-param-list>

implements interface-name<type-param-list> {//...

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]