1

我昨天在这里发布了这个问题的(looong)版本: 类型差异问题

为了缩短(真的)长话短说,这个:

 class A[-P, T <: P]

不编译(它抱怨说“P 出现在类型 <: T 类型的 P 中的协变位置”)。对我之前的问题的回答表明该声明确实无效,因为A[Foo, Bar]它将是 的子类A[Nothing, Bar],但后者是非法的(Bar不是 的子类Nothing)。

我不认为这是足够的理由。按照这种逻辑,这样的事情也应该是非法的:class B[+T <: String]-B[String]应该是的子类,B[Any]但后者是无效的。

此外,这:

class C[T, -P >: T] 

实际上确实编译。这与上面的内容本质上不一样A吗?

4

1 回答 1

1

这些是微妙的不同。

class Test[-P, T <: P]

说“让我们P成为一个逆变和无界变化的类型参数,让我们T成为 . 的子类型P。” 也就是说,T在检查类型是否对 有效时完全忽略P。只有 thenT才被限制为 的子类型P。这是非法的,原因你已经知道了。你可以从 开始Test[Any, String],因为P它是无限逆变的,所以它可以变成Test[Nothing, String],突然之间你有了String <: Nothing

class tseT[T, -P :> T] // Code highlighters HATE him. Click to find out why.

说“让我们T成为一个不变且无界的类型参数,然后让我们P成为一个下界的逆变类型参数T。” 这有点不同,因为这次P的方差受下限的限制TP仍然是逆变的,但不能低于T,否则会违反P >: T。这是安全的,因为您可以从 开始tseT[String, Any],然后P只要它仍然是 的超类型,就只能向下变化String,因此P向下变化到是非法的Nothing

请注意,类型参数是从左到右处理的。这就是为什么第一个示例被声明为无效的原因,而不是推断 bound P >: T,因为在处理T时尚未声明P,并且这样的 bound 无论如何都是前向引用。

于 2017-08-19T01:51:30.327 回答