请考虑以下代码段:
trait X[-T]
object Y extends X[Nothing]
def a[T](x: X[T]): X[T] = x
a(Y)
以上(2.12.3)的汇编失败,并且:
type mismatch;
found : Y.type
required: X[T]
a(Y)
^
如果符合以下条件,则编译正常:
Nothing
不同的类型(例如object Y extends X[String]
)a
在其返回类型中不使用T
(例如def a[T](x: X[T]): Unit = {}
)a
的类型参数(即a[Nothing](Y)
)T
是协变的,而不是逆变的(如果它不变则也会失败)这是Nothing
的编译器中的一些特例吗?
作为一个有趣的"解决方法,以下似乎工作正常:
trait X[-T]
object Y extends X[Nothing]
def a[T, U <: T](x: X[T]): X[U] = x
a(Y)
答案 0 :(得分:1)
我将尝试逐行解释代码
第1行:trait X[-T]
- &gt;特征X在类型T中是逆变的。因此,您可以用其子类型替换X [T]类型的任何变量。在逆变类型的情况下,如果B是A的子类型,则Z [A]是Z [B]的子类型。
第2行:object Y extends X[Nothing]
- &gt;对象Y的类型为X [Nothing]。请注意,Nothing不是所有其他类型的子类型。
第3行:def a[T](x: X[T]): X[T] = x
- &gt;定义一个带有X [T]类型参数的表达式。因为特征X在类型T中是逆变的,所以你也可以传递X [T]的子类型,即X [N],使得T是N的子类型
第4行:a(Y)
- &gt;使用类型X [Nothing]的参数调用表达式“a”。由于编译器不知道'a'的参数类型,因此无法确定X [Nothing]是否是X [T]的子类型。有多种方法可以解决此问题
Solution 1: `a[Nothing]` -> explicitly defining the type
Solution 2: `tait X[+T]` -> make X covariant in type T. In this case Z[A] is subtype of Z[B] if A is subtype of B. This will work because Nothing is subtype of any other type