Общие параметры Java и наследование - PullRequest
1 голос
/ 03 августа 2011

предполагается, что мы знаем, что ViewGroup расширяет View.
Далее у нас есть общий, параметризованный class A<T extends View>

Вопрос:
Почему метод C.add() принимает new A<ViewGroup>() в качестве параметра?
Разве это не должно работать из-за полиморфизма?

Class diagram

РЕШЕНИЕ: Пение добавляется с ? extends View позволяет добавить принять new A<ViewGroup>() какпараметр.

Solution

Ответы [ 4 ]

7 голосов
/ 03 августа 2011

Вы подписали свой метод add как:

static void add(A<View>)

, но вы, вероятно, имели в виду:

static void add(A<? extends View> a)
1 голос
/ 03 августа 2011

Прежде всего вы сказали, что View расширяет ViewGroup, но на диаграмме сказано, что ViewGroup расширяет View (что я считаю правильным).

Во-вторых, вам не разрешено передавать List<ViewGroup> как List<View>. Это защита во время компиляции, которая не позволяет кому-либо добавить AnotherView в этот список и ставит под угрозу безопасность типов обобщений.

List<ViewGroup> не является подтипом List<View>, но это подтип List<? extends View>. Таким образом, вы можете изменить свой метод так, чтобы вместо него принимать List<? extends View>, но имейте в виду, что вы не можете добавить в список, переданный методу таким образом.

Существует также другой синтаксис, называемый подстановочным знаком нижней границы (List<? super ViewGroup>), в отличие от упомянутого выше подстановочного знака верхней границы, который позволяет добавлять в список, но вы можете в любой момент передать список ViewGroup или его родителей.

Подробнее о подстановочных знаках в дженериках можно найти здесь: http://download.oracle.com/javase/tutorial/java/generics/wildcards.html

1 голос
/ 03 августа 2011

Прежде всего, ваш вопрос не очень понятен, потому что UML-диаграмма противоречит вашему тексту.Вы говорите, что View расширяет ViewGroup, но диаграмма показывает обратное: ViewGroup расширяет View.

Теперь List<Car> не расширяет List<Vehicle>.Если бы это было так, вы могли бы сделать:

List<Car> listOfCars = new ArrayList<Car>();
List<Vehicle> listOfVehicles = listOfCars;
listOfVehicles.add(new Bicycle());
// now the list of cars contain a bicycle. Not pretty. 
1 голос
/ 03 августа 2011

Не совсем, потому что add() может использовать метод View, которого нет в ViewGroup.

Резюме: View - это ViewGroup, однако ViewGroup - это не View. Полиморфизм - это место, где вы можете назначить объект View объявлению ViewGroup.

...