Spec-Zone .ru
спецификации, руководства, описания, API
След: Изучение Языка Java
Урок: (Обновленные) Обобщения
Обобщения, Наследование, и Подтипы
Домашняя страница > Изучение Языка Java > (Обновленные) обобщения

Обобщения, Наследование, и Подтипы

Как Вы уже знаете, возможно присвоить объект одного типа к объекту другого типа при условии, что типы являются совместимыми. Например, можно присвоить Integer Object, так как Object является одним из супертипов Integer:

Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger;   // OK

В объектно-ориентированной терминологии это вызывают, "" отношение. Так как Integer является своего рода Object, присвоение позволяется. Но Integer является также своего рода Number, таким образом, следующий код допустим также:

public void someMethod(Number n) { /* ... */ }

someMethod(new Integer(10));   // OK
someMethod(new Double(10.1);   // OK

То же самое является также истиной с обобщениями. Можно выполнить универсальный вызов типа, передавая Number как его параметр типа, и любой последующий вызов add будет позволен, если параметр будет совместимым с Number:

Box<Number> box = new Box<Number>();
box.add(new Integer(10));   // OK
box.add(new Double(10.1));  // OK

Теперь рассмотрите следующий метод:

public void boxTest(Box<Number> n) { /* ... */ }

Какой параметр это принимает? Смотря на его подпись, можно видеть, что это принимает единственный параметр, типом которого является Box<Number>. Но что это означает? Вам разрешают передать в Box<Integer> или Box<Double>, как Вы могли бы ожидать? Ответ является "нет", becaue Box<Integer> и Box<Double> не являются подтипами Box<Number>.

Это - распространенное заблуждение когда дело доходит до программирования с обобщениями, но это - важное понятие, чтобы учиться.

схема показывая, что Поле <Целое число> не является подтипом Поля <Число>
Box<Integer> не является подтипом Box<Number> даже при том, что Integer является подтипом Number.

Отметьте: Учитывая два типа бетона у A и B (например, Number и Integer), MyClass<A> нет никакого отношения к MyClass<B>, независимо от того, связываются ли A и B. Общим родителем MyClass<A> и MyClass<B> является Object.

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

Универсальные Классы и Выделение подтипов

Можно выделить подтипы в универсальном class или взаимодействовать через интерфейс, расширяясь или реализовывая его. Отношение между параметрами типа одного class или интерфейса и параметрами типа другого определяется пунктами implements и extends.

Используя классы Collections как пример, ArrayList<E> реализует List<E>, и List<E> extends Collection<E>. Таким образом, ArrayList<String> является подтипом List<String>, который является подтипом Collection<String>. Пока Вы не изменяете параметр типа, отношение выделения подтипов сохраняется между типами.

схема показывая демонстрационную иерархию наборов: ArrayList <Строка> является подтипом Списка <Строка>, которая является подтипом Набора <Строка>.
Демонстрационная иерархия Collections

Теперь предположите, что мы хотим определить наш собственный интерфейс списка, PayloadList, который связывает дополнительное значение универсального типа P с каждым элементом. Его объявление могло бы быть похожим:

interface PayloadList<E,P> implements List<E> {
  void setPayload(int index, P val);
  ...
}

Следующая параметризация PayloadList является подтипами List<String>:

схема показывая пример иерархия PayLoadList: PayloadList <Строка, Строка> является подтипом Списка <Строка>, которая является подтипом Набора <Строка>. На том же самом уровне PayloadList <Строка, Строкой> является PayloadList <Строка, Целое число> и PayloadList <Строка, Исключения>.
Демонстрационная иерархия PayloadList

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Универсальные Методы и Ограниченные Параметры Типа
Следующая страница: Вывод типа