Подтвердить что ты не робот

Многоуровневое наследование с использованием общих расширений на основе общих параметров

У меня

public class First<T> {}

public class Second<T extends SomeConcreteClass> extends First<T> {}

public class Third<T> extends Second<T> {} //Compile-time error

Я получаю ошибку времени компиляции

Type argument T is not with bounds of type-variable T.

Когда я создаю a Third, я хочу предоставить общий параметр как SomeConcreteClass (или его производный класс), а также для ошибки времени выполнения, если я предложил тип который не является частью иерархии наследования SomeConcreteClass.

Я бы подумал, что спецификация в объявлении Second будет просто распространяться вниз, т.е. она должна быть неявной в объявлении (и любых экземплярах) Third.

Что с ошибкой?

4b9b3361

Ответ 1

Все, что вам нужно, это

public class Third<T extends SomeConcreteClass> extends Second<T>

Вам просто нужно отрегулировать привязку. Он не распространяется так, как вы думаете.

(Я не уверен в этой причине, но у меня есть некоторые догадки - что, если это было Third<T> extends Second<Foo<T>>? Соответствующая оценка на T не очевидна, если ее даже нет., он просто не распространяется автоматически, вы должны указать его.)

Ответ 2

У вас есть нисходящее распространение граничного ограничения.

Если вы поместите свой код выше в родовых терминах, вы увидите четкую декларацию. Кроме того, любое дальнейшее наследование также необходимо будет сохранить или ограничить это ограничение. например:

public class First<T> {}

public class Second<U, T1 extends U> extends First<T1> {}

public class Third<V, T2 extends V> extends Second<V,T2> {} 

Обратите внимание, что теперь ясно, что вы не можете

public class Third<T> extends Second<T> {} 

Как вам не хватает информации о типе T2 для Second<V,T2>. Когда вы используете конкретный класс, это ограничение становится неявным.

Ответ 3

В нашем случае вы, вероятно, можете заменить это:

public class Third<T> extends Second<T> {}

с этим:

public class Third extends Second<SomeConcreteClass> {}

Чтобы использовать T внутри конструктора и в противном случае в коде, таком как поле члена типа T, вы можете сделать вот так:

VB2 extends VB1<Frag2>
...
public VB2(Frag2 frag){...

VB1<T extends Frag1> extends CommonVB<T>
...
public V1(T frag){... /// notice the T

CommonV<T extends CommonFragBase> extends BaseVB<T>
...
public CommonVB(T controller) {...

BaseVB<T extends CommonFragBase>

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

Ответ 4

public class Third<T> extends Second<T> {}

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

public class Third<T> extends Second<ClassThatExtendsSomeConcreteClass> {}

или просто

public class Third<T> extends Second<SomeConcreteClass> {}