Java Наследование сомнений в параметризованной коллекции - PullRequest
4 голосов
/ 07 июня 2010

Очевидно, что объект родительского класса может содержать ссылку на дочерний элемент, но разве это не выполняется в случае параметризованного сбора ??

например:

Car class is parent of Sedan

Итак

public void doSomething(Car c){
    ...
}

public void caller(){
    Sedan s = new Sedan();
    doSomething(s);
}

очевидно действителен

Но

public void doSomething(Collection<Car> c){
    ...
}

public void caller(){
    Collection<Sedan> s = new ArrayList<Sedan>();
    doSomething(s);
}

Не компилируется

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

Конечно, это прекрасно скомпилируется, если я сделаю так:

public void doSomething(Collection<Car> c){
    ...
}

public void caller(){
    Collection s = new ArrayList<Sedan>();
    doSomething(s);
}

Ответы [ 2 ]

4 голосов
/ 07 июня 2010

Используйте

public void doSomething(Collection<? extends Car> c){}

или (как предложено)

public <T extends Car> void doSomething(Collection<T> c){}

Это будет означать, что Collection относится к любому подклассу Car (или Car), а не к "Это только набор Car экземпляров"

Это потому, что коллекции инвариантны , в отличие от массивов, которые ковариантны . Цитировать Эффективная Java :

Ковариант [..] означает, что если Sub является подтипом Super, то тип массива Sub[] является подтипом Super[]. Дженерики, напротив, инвариантны : для любых двух различных типов Type1 и Type2, List<Type1> ни подтип, ни супертип List<Type2>.

2 голосов
/ 07 июня 2010

doSomething необходимо объявить doSomething(Collection<? extends Car> c). Заявленный таким образом, вы не сможете добавлять какие-либо элементы в коллекцию, поскольку вы не знаете, какой конкретный подкласс Car должен содержать эта коллекция.

Общая проблема здесь в том, что Collection<Sedan> просто не может считаться подклассом Collection<Car>, потому что вы не можете делать все на Collection<Sedan>, что вы можете на Collection<Car>. Например, вы можете add a SportsCar до Collection<Car>, потому что SportsCar - это Car. Вы не можете добавить SportsCar к Collection<Sedan>, потому что SportsCar не является Sedan.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...