Scala ::列表中的方法-逆变参数类型

Scala ::列表中的方法-逆变参数类型,scala,generics,Scala,Generics,一个简单的问题。类immutableList的方法:定义为: 密封抽象类列表[+A] 定义::[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) 现

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

密封抽象类列表[+A]

定义::[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)

现在我在这里感到困惑。根据
声明,参数类型应该是反变的。i、 e.在这种情况下,任何
:Fruit
(我理解为什么会这样做)的类。但是我不明白的是,
Mango你仍然可以将
Mango
添加到
d
中,即使
列表
是不变的,仅仅因为
Mango
仍然是一个
水果
。从一个简单的旧java列表来考虑:

val d = new java.util.ArrayList[Fruit]
d.add(new Mango)
因此,相反,它不会限制您添加子类型的能力—它允许您添加超类型并从中获取编译器检查列表类型:

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

new Mango :: d
您希望编译器进行推理:“
newmango
具有类型
Mango
d
具有类型
List[four]
,因此
List[four]::(Mango)
需要进行类型检查,而它没有这样做”。在这种情况下,这确实是一个错误


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

同意。这是
列表的属性。但在这里,该方法对参数的类型进行了限制。它应该是
\uu>:Fruit
,但它的行为是
\uu不,它的行为不是
\uu。我尝试重新表述它:该方法需要一个
B
类型的参数,它是
a
的非严格超类型,即
B>:a
。结果列表将具有最特定的通用超类型。例如,当
A=水果
B=芒果
时,你会得到一个
列表[水果]
;当
A=水果
B=植物
时,您会得到一个
列表[植物]
。总而言之:该方法旨在让您构建更通用的类型容器,而不是限制您添加特定的子类型(顺便说一句,根据Liskov,这是不可能的)