请考虑以下代码片段:
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)
我将尝试逐行解释代码
第 1 行:trait X[-T]
->性状 X 在 T 型中是逆变的。因此,您可以将任何 X[T] 类型的变量替换为其子类型。在逆变类型的情况下,如果 B 是 A 的亚型,则 Z[A] 是 Z[B] 的亚型。
第 2 行:object Y extends X[Nothing]
->对象 Y 的类型为 X[无]。请注意,Nothing 是所有其他类型的子类型。
第 3 行:def a[T](x: X[T]): X[T] = x
->定义一个接受 X[T] 类型参数的表达式。因为性状 X 在 T 型中是逆变的,你也可以传递 X[T] 的子类型,即 X[N],使得 T 是 N 的亚型
第 4 行:a(Y)
-> 调用表达式 'a' ,参数类型为 X[Nothing]。由于编译器不知道 '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