10

考虑以下代码段:

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]
  • 该方法aT在其返回类型中使用(例如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)
4

1 回答 1

1

我将尝试逐行解释代码

第 1 行:trait X[-T]-> trait X 在类型 T 中是逆变的。因此,您可以将 X[T] 类型的任何变量替换为其子类型。在逆变类型的情况下,如果 B 是 A 的子类型,则 Z[A] 是 Z[B] 的子类型。

第 2 行:object Y extends X[Nothing]-> 对象 Y 的类型为 X[Nothing]。请注意,Nothing 是所有其他类型的子类型。

第 3 行:def a[T](x: X[T]): X[T] = x-> 定义一个接受 X[T] 类型参数的表达式。因为特征 X 在类型 T 中是逆变的,所以您还可以传递 X[T] 的子类型,即 X[N] 使得 T 是 N 的子类型

第 4 行:a(Y)-> 使用 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
于 2018-01-24T17:35:01.717 回答