题
有什么区别
[A <: B]
和
[+B]
在Scala?
解决方案
Q[A <: B]
意味着该课程 Q
可以参加任何课程 A
那是一个子类 B
.
Q[+B]
意思是 Q
可以采取 任何 班级,但如果 A
是 B
, , 然后 Q[A]
被认为是 Q[B]
.
Q[+A <: B]
意味着该课程 Q
只能参加 B
以及传播子类关系。
当您想执行通用的事情时,第一个很有用,但是您需要依靠一系列方法 B
. 。例如,如果您有 Output
上课 toFile
方法,您可以在可以传递到的任何类中使用该方法 Q
.
当您想制作与原始类相同的收藏时,第二个很有用。如果你服用 B
你做了一个子类 A
, ,那么你可以通过 A
在任何地方 B
是期待。但是,如果您服用 收藏 的 B
, Q[B]
, ,您总是可以传递吗? Q[A]
反而?通常,不;在某些情况下,这是错误的事情。但是您可以说这是正确的选择 +B
(协方差; Q
协变量 - 与 -B
的子类的继承关系)。
其他提示
我想扩展 雷克斯·克尔(Rex Kerr)的出色答案 还有一些例子:假设我们有四个类:
class Animal {}
class Dog extends Animal {}
class Car {}
class SportsCar extends Car {}
让我们从差异开始:
case class List[+B](elements: B*) {} // simplification; covariance like in original List
val animals: List[Animal] = List( new Dog(), new Animal() )
val cars: List[Car] = List ( new Car(), new SportsCar() )
如你看到的 列表不在乎它是否包含动物还是汽车. 。列表的开发人员没有强制执行,例如,只有汽车才能进入列表。
此外:
case class Shelter(animals: List[Animal]) {}
val animalShelter: Shelter = Shelter( List(new Animal()): List[Animal] )
val dogShelter: Shelter = Shelter( List(new Dog()): List[Dog] )
如果功能期望 List[Animal]
参数您也可以通过 List[Dog]
作为函数的参数。 List[Dog]
被认为是 List[Animal]
由于清单的协方差。如果列表不变,则行不通。
现在进入类型范围:
case class Barn[A <: Animal](animals: A*) {}
val animalBarn: Barn[Animal] = Barn( new Dog(), new Animal() )
val carBarn = Barn( new SportsCar() )
/*
error: inferred type arguments [SportsCar] do not conform to method apply's type parameter bounds [A <: Animal]
val carBarn = Barn(new SportsCar())
^
*/
如你看到的 谷仓是一个仅针对动物的收藏品. 。这里不允许汽车。
为了理解:
第一个是绑定的参数类型,在我们的情况下,上部和较低的类型是“类型参数A,它是B(或B本身)的子类型。
第二个是对班级定义的差异注释,在我们的情况下,B的协方差子类别
Scala: + Java:?扩展T协变量子类
Scala:-java:?超级T逆转子类
我在研究这个问题时找到了这篇博客文章。对Scala差异提供了更深入的解释,包括其在类别理论中的理论基础
http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/