简体   繁体   English

Scala中A <:B和+ B之间有什么区别?

[英]What's the difference between A<:B and +B in Scala?

What's the difference between 有什么区别

[A <: B]

and

[+B]

in Scala? 在斯卡拉?

Q[A <: B] means that class Q can take any class A that is a subclass of B . Q[A <: B]表示类Q可以接受任何作为B的子类的A类。

Q[+B] means that Q can take any class, but if A is a subclass of B , then Q[A] is considered to be a subclass of Q[B] . Q[+B]表示Q可以取任何类,但如果AB的子类,则Q[A]被认为是Q[B]的子类。

Q[+A <: B] means that class Q can only take subclasses of B as well as propagating the subclass relationship. Q[+A <: B]意味着类Q只能获取B的子类以及传播子类关系。

The first is useful when you want to do something generic, but you need to rely upon a certain set of methods in B . 当你想要做一些通用的东西时,第一个是有用的,但你需要依赖B的某些方法。 For example, if you have an Output class with a toFile method, you could use that method in any class that could be passed into Q . 例如,如果您有一个带有toFile方法的Output类,则可以在任何可以传递给Q类中使用该方法。

The second is useful when you want to make collections that behave the same way as the original classes. 当您想要使集合的行为与原始类相同时,第二个非常有用。 If you take B and you make a subclass A , then you can pass A in anywhere where B is expected. 如果你拿B并且你创建了一个子类A ,那么你可以在任何预期B地方传递A But if you take a collection of B , Q[B] , is it true that you can always pass in Q[A] instead? 但是如果你收集一个BQ[B]集合 ,你是否可以总是传入Q[A]而不是? In general, no; 一般来说,没有; there are cases when this would be the wrong thing to do. 有些情况下这是错误的做法。 But you can say that this is the right thing to do by using +B (covariance; Q covaries--follows along with-- B 's subclasses' inheritance relationship). 但你可以说通过使用+B (协方差; Q covaries - 跟随 - B的子类的继承关系)这是正确的做法。

I would like to extend Rex Kerr's excellent answer with some more examples: Let's say we have four classes: 我想用更多的例子来扩展Rex Kerr的优秀答案 :假设我们有四个类:

 class Animal {}
 class Dog extends Animal {}

 class Car {}
 class SportsCar extends Car {}

Let's start with variance: 让我们从方差开始:

 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() )

As you can see List does not care whether it contains Animals or Cars . 如您所见, List并不关心它是否包含动物或汽车 The developers of List did not enforce that eg only Cars can go inside Lists. List的开发人员没有强制执行,例如只有汽车可以进入列表。

Additionally: 另外:

case class Shelter(animals: List[Animal]) {}

val animalShelter: Shelter = Shelter( List(new Animal()): List[Animal] )
val dogShelter: Shelter = Shelter( List(new Dog()): List[Dog] )

If a function expects a List[Animal] parameter you can also pass a List[Dog] as an argument to the function instead. 如果函数需要List[Animal]参数,您也可以将List[Dog]作为参数传递给函数。 List[Dog] is considered a subclass of List[Animal] due to the covariance of List. 由于List的协方差,List List[Dog] 被认为是 List[Animal] 的子类 It would not work if List was invariant. 如果List不变,它将无法工作。

Now onto type bounds: 现在进入类型边界:

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())
                 ^
*/

As you can see Barn is a collection only intended for Animals . 正如您所见, Barn是一个仅供动物使用的系列 No cars allowed in here. 这里没有车。

I found this blog post while researching this question. 我在研究这个问题时发现了这篇博文。 Gives an even deeper explanation of Scala variance including its theoretical basis in Category Theory 对Scala方差进行了更深入的解释,包括其在范畴论中的理论基础

http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/ http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

for my Understanding: 对于我的理解:


The first is a parameter type bound, there a upper and lower typebounds in our case its a "type parameter A that is a subtype of B (or B itself). 第一个是参数类型绑定,在我们的例子中有一个上限和下限类型,它是一个“类型参数A,它是B的一个子类型(或B本身)。


The second is a Variance Annotation for a class defintion, in our case a covariance subclassing of B 第二个是类定义的方差注释,在我们的例子中是B的协方差子类


Scala: + Java: ? Scala:+ Java :? extends T Covariant subclassing 扩展T Covariant子类

Scala: - Java: ? 斯卡拉: - Java :? super T Contravariant subclassing super T Contravariant子类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM