Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на Java.docx
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
3.45 Mб
Скачать

Тема 5.6 Универсальные интерфейсы

Наряду с универсальными классами и методами существуют также универсальные интерфейсы. Универсальные интерфейсы определяются точно так же, как и универсальные классы. Их использование иллюстрирует следующий пример. В нем создается интерфейс Containment, который может быть реализован классами, хранящими одно или несколько значений. Кроме того, в нем объявлен метод contains(), который определяет, содержится ли указанное значение в текущем объекте.

Листинг 5.7

// Данный интерфейс подразумевает, что

// реализующий его класс содержит одно или несколько значений

public interface Containment<T> {

// Метод contains() проверяет, содержится ли

// некоторый элемент в составе объекта, реализующего Containment

public boolean contains(T o);

}

// Реализация интерфейса Containment с использованием

// массива, предназначенного для хранения значений.

// Любой класс, реализующий универсальный интерфейс,

// также должен быть универсальным

public class MyClass<T> implements Containment<T> {

private T[] arrayRef;

public MyClass(T[] o) {

arrayRef = o;

}

public boolean contains(T o) {

for (T x : arrayRef) {

if (x.equals(o)) {

return true;

}

}

return false;

}

}

public class GenIFDemo {

public static void main(String args[]) {

Integer x[] = {1, 2, 3};

MyClass<Integer> ob = new MyClass<Integer>(x);

if (ob.contains(2)) {

System.out.println("2 is in ob");

} else {

System.out.println("2 is NOT in ob");

}

if (ob.contains(5)) {

System.out.println("5 is in ob");

} else {

System.out.println("5 is NOT in ob");

}

// Следующие строки кода недопустимы, так как ob

// представляет собой вариант Integer

// реализации интерфейса Containment, а 9.25 —

// это значение Double

// if(ob.contains(9.25)) // Illegal!

// System.out.println("9.25 is in ob");

}

}

В основном элементы этой программы просты для восприятия, однако на некоторых ее особенностях следует остановиться. Прежде всего обратите внимание на то, как определен интерфейс Containment,

public interface Containment<T> {

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

public class MyClass<T> implements Containment<T> {

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

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

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

public class MyClass implements Containment<Double> { // 0K

Наверное, вы не удивитесь, узнав, что один или несколько параметров типа для универсального интерфейса могут быть ограничены. Это позволяет указывать, какие типы данных допустимы для интерфейса. Например, если вы хотите запретить передачу Containment значений, не являющихся числовыми, вы можете использовать объявление

public interface Containment<T extends Number> {

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

public class MyClass<T extends Number> implements Containment<T> {

Обратите особое внимание на то, как параметр типа T объявляется в классе Myclass, а затем передается интерфейсу Containment. Поскольку на этот раз интерфейсу Containment требуется тип, расширяющий Number, в классе, peaлизующем интерфейс (в данном случае это MyClass), должны быть определены соответствующие ограничения. Если верхняя граница задана в определении класса, то нет необходимости еще раз указывать ее в выражении implements Более того, если вы попытаетесь сделать это, получите сообщение об ошибке. Например, следующее выражение некорректно и не будет компилироваться:

// Ошибка!

public class MyClass<T extends Number> implements Containment<T extends Number> {

Если параметр типа задан в определении класса, он лишь передается интерфейсу без дальнейшей модификации.

Формат объявления универсального интерфейса выглядит следующим образом:

public interface имя_интерфейса<параметры_типа> { // ...

Здесь параметры типа в составе списка разделяются запятыми. При реализации интерфейса имя класса также должно сопровождаться параметрами типа. Выражение, с помощью которого определяется класс, реализующий интерфейс, показано ниже.

class имя_класса<параметры_типа>

implements имя_интерфейса<параметры_типа> {

Задание:

Разработать очередь в которой можно хранить объекты любых типов. Методами get() и set() можно извлечь и добавить объект. Предусмотреть обработку исключений в случае переполнения и пустой очереди.