Вот мое понимание.
Предположим, что у нас есть общий тип с 2-мя методами
type L<T>
T get();
void set(T);
Предположим, что у нас есть супер тип P
, и он имеет подтипы C1, C2 ... Cn
. (Для удобства мы говорим P
является подтипом самого по себе, а на самом деле один из Ci
)
Теперь мы также получили п конкретных типов L<C1>, L<C2> ... L<Cn>
, как если бы мы вручную написаны п типов:
type L_Ci_
Ci get();
void set(Ci);
Нам не пришлось вручную писать их, вот в чем вопрос. Там нет нет отношения между этими типами
L<Ci> oi = ...;
L<Cj> oj = oi; // doesn't compile. L<Ci> and L<Cj> are not compatible types.
Для шаблона C++, что это конец истории. Это, в основном, макрораспределение - основано на одном классе «шаблон», оно генерирует много конкретных классов, без отношения типа между ними.
Для Java существует больше. Мы также получили тип L<? extends P>
, это тип супер любого L<Ci>
L<Ci> oi = ...;
L<? extends P> o = oi; // ok, assign subtype to supertype
Какой метод должен существовать в L<? extends P>
? Как супер тип, любой из его методов должен быть опознан подтипами. Этот метод будет работать:
type L<? extends P>
P get();
, потому что ни в одном из его подтипов L<Ci>
, есть метод Ci get()
, который совместит с P get()
- наиважнейший методом имеет ту же сигнатуру и ковариантный типа возвращаемого значения.
Это не может работать set()
, хотя - мы не можем найти тип X
, так что void set(X)
может быть преодолено void set(Ci)
для любого Ci
. Поэтому set()
метод не существует в L<? extends P>
.
Также есть L<? super P>
, который идет в другую сторону. Он имеет set(P)
, но не get()
. Если Si
является супер-типом P
, L<? super P>
- это супер тип L<Si>
.
type L<? super P>
void set(P);
type L<Si>
Si get();
void set(Si);
set(Si)
«переопределение» set(P)
не в обычном смысле этого слова, но компилятор может видеть, что любой допустимый вызов на set(P)
является действительным вызовом на set(Si)
Дурной пример полиморфизма, я думаю? «Ребенок» не является (всегда) «родителем». – justhalf
@justhalf: 'Parent' был в вопросе и предполагает, что' Child' является естественным примером подкласса. Не имена классов, которые я выбрал бы с нуля, но достаточно понятные с точки зрения контекста, о котором идет речь. –
Да, я понимаю, но я думаю, было бы лучше, если бы здесь использовался «SingleParent» или «NewParent» в качестве подкласса =) – justhalf