这是我的理解。
假设我们有一个泛型类型,有两个方法type L
T get();
void set(T);
假设我们有一个超级类型P,而且它有子类型C1, C2 ... Cn..(为了方便起见,我们说P是自身的一个子类型,实际上是Ci)
现在我们也有n混凝土类型L, L ... L,就好像我们已经手动写了n类型:type L_Ci_ Ci get();
void set(Ci);
我们不需要手动写,这就是重点。确实有不这些类型之间的关系L oi = ...;L oj = oi; // doesn't compile. L and L are not compatible types.
对于C+模板来说,这就是故事的结尾。它基本上是宏扩展-基于一个“模板”类,它生成许多具体的类,它们之间没有类型关系。
对于Java来说,还有更多。我们也有一种L extends P>,它是任何一个超级类型的LL oi = ...;L extends P> o = oi; // ok, assign subtype to supertype
什么样的方法应该存在于L extends P>?作为一个超级类型,它的任何方法都必须由它的子类型来预测。这种方法将起作用:type L extends P>
P get();
因为它的任何一个子类型L,有一种方法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.type L super P>
void set(P);type L
Si get();
void set(Si);
set(Si)“重写”set(P)不是通常意义上的,但是编译器可以看到set(P)上的有效调用。set(Si)