:: List中的方法 - 逆变参数类型

时间:2013-02-15 11:57:29

标签: scala generics

一个简单的问题。类不可变::的方法List定义为:

  

密封抽象类列表[+ A] ...

     

def :: [B>:A](x:B):列出[B]

假设我说:

class Fruit
class Mango extends Fruit
scala> val d:List[Fruit] = List.empty[Fruit]
d: List[Fruit] = List()

scala> new Mango :: d
res5: List[Fruit] = List(Mango@272d6774)

现在我很困惑。根据{{​​1}}声明,参数类型应该是逆变的。即在这种情况下::的任何一类(我理解为什么这样做)。但我得到的是>: Fruit,那么为什么编译器不会抛出错误?

2 个答案:

答案 0 :(得分:5)

即使Mango不变,您仍然可以将d添加到List,因为Mango仍然是Fruit。根据普通的旧Java列表来考虑它:

val d = new java.util.ArrayList[Fruit]
d.add(new Mango)

因此,逆变不会限制您添加子类型的能力 - 它使您能够添加超类型并从中获取编译器检查的列表类型:

val d: List[Fruit] = Nil
val a: List[Plant] = new Carrot :: d

答案 1 :(得分:3)

在第

new Mango :: d

您希望编译器推理:“new Mango的类型为Mango,而d的类型为List[Fruit],因此List[Fruit].::(Mango)需要进行类型检查,而不是“T”。在这种情况下,它确实是一个错误。

但事实上,它的理由不同:“我需要new Mango :: d进行类型检查,因此new Mango必须某些类型B,以便B :> Fruit是否有这样的B?是的,B = Fruit。“所以没有错误。