以下代码无法编译(在Scala 2.11中):
case class CovariantClass[+R](value: R) {
type T = R
def get: R = value
}
object Main {
def main(args: Array[String]): Unit ={
println(CovariantClass[String]("hello").get)
}
}
错误消息是:
Error:(4, 8) covariant type R occurs in invariant position in type R of type T
type T = R
^
为什么我不能为协变类型参数添加别名?如果我删除行type T = R
,代码将编译并打印hello
,因此别名似乎是问题所在。不幸的是,这意味着我无法为更复杂的类型创建别名,例如,type T = List[R]
也不会编译,尽管List
是协变的。
答案 0 :(得分:5)
来自scala spec:
类型别名的右侧始终处于不变位置。
这意味着您无法创建别名T
并在右侧指定变体类型R
。这同样适用于List[R]
,因为它也是协变的。
你可以,但是提供带有类型参数的类型别名:
case class CovariantClass[+R](value: R) {
type T[+R] = List[R]
def get: R = value
}
如果您发现自己想要为类型参数R
添加别名,那么您应该首先将其命名为其他内容。
答案 1 :(得分:4)
它是被禁止的,因为它会允许一个不正确的程序,这始终是规则。你可以像这样重写它:
case class CovariantClass[+R](value: R) {
type T <: R
def get: R = value
}
关于它如何破坏的一个例子,考虑一下:
case class CovariantClass[+R](value: R) {
type T = Int
def get: R = value
def put(x: T) {}
def put2(x: R) {}
}
由于T
的定义方式,它是不变的。这意味着它可以用在协变类型不能的地方,如上所示。请注意put
编译但put2
不编译。