вопрос об интерфейсах и обобщениях в Java: ошибка несоответствия типов - PullRequest
2 голосов
/ 02 сентября 2011

Предположим, у меня есть следующий интерфейс:

public interface Interface<T extends Number>{
    public Vector<Interface<T>> getVector();
}

и следующий класс, реализующий этот интерфейс:

public abstract class C<T extends Number> implements Interface<T>{

    private Vector<C<T>> vector;
    public Vector<Interface<T>> getVector(){ //errror
         return this.vector;
    }
} 

Почему не разрешено возвращать Vector<C<T>>, в то время как допустимо (очевидно,) возвращая Vector<Interface<T>>.C на самом деле реализует Interface, так что это должно быть возможно, верно?Чего мне не хватает?

РЕДАКТИРОВАТЬ:

Почему это работает для не универсального интерфейса?Это на самом деле общая проблема?

public interface Interface{
        public Interface getVector();
    }

public abstract class C implements Interface {

    private C;
    public Interface getVector(){ //errror
         return this.c;
    }
} 

Ответы [ 2 ]

2 голосов
/ 02 сентября 2011

Поскольку Vector явно состоит из Interface<T>, а не вещей, которые расширяют Interface<T>, я считаю, что это сработает, если вы измените определение на

 public Vector<? extends Interface<T>> getVector();

Проблема в том, что для некоторых V implements T или V extends T Foo<V> не является супертипом Foo<T>. Компилятор не проверяет наследование общих аргументов, если вы явно не укажете эту точку расширения.

Использование Vector<? extends Interface<T>> означает «разрешить любой класс, который реализует или расширяет Interface<T>, тогда как Vector<Interface<T>> означает вектор, состоящий только из Interface<T> элементов.

Возможно, более конкретно следует учитывать, что List<Integer> не является приемлемой заменой для List<Number>, несмотря на то, что Integer расширяет Number по той же причине.

обновление

Я протестировал этот и следующие компиляторы без каких-либо ошибок или предупреждений

interface Interface<T extends Number>{
    public Vector<? extends Interface<T>> getVector();
}

abstract class C<T extends Number> implements Interface<T>{

    private Vector<C<T>> vector;
    public Vector<? extends Interface<T>> getVector(){
         return this.vector;
    }
} 
1 голос
/ 02 сентября 2011

Так работают дженерики.Они не являются «ковариантными»: если у вас есть класс AClass и его подкласс SubAClass, Vector<SubAClass> не является подклассом Vector<A>.(Однако обратите внимание, что SubAClass[] является подклассом AClass[].)

РЕДАКТИРОВАТЬ:

На первый взгляд очевидное:

public ArrayList<Object> blah() {
    return new ArrayList<String>();
}

не будет компилироваться, потому что ArrayList<String> не является подклассом ArrayList<Object>.Так что в вашем случае вы не можете вернуть Vector<C<T>> экземпляр для Vector<Interface<T>>.

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