Scala ::列表中的方法-逆变参数类型
一个简单的问题。类immutableScala ::列表中的方法-逆变参数类型,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) 现
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,这是不可能的)