簡體   English   中英

Scala中A <:B和+ B之間有什么區別?

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

有什么區別

[A <: B]

[+B]

在斯卡拉?

Q[A <: B]表示類Q可以接受任何作為B的子類的A類。

Q[+B]表示Q可以取任何類,但如果AB的子類,則Q[A]被認為是Q[B]的子類。

Q[+A <: B]意味着類Q只能獲取B的子類以及傳播子類關系。

當你想要做一些通用的東西時,第一個是有用的,但你需要依賴B的某些方法。 例如,如果您有一個帶有toFile方法的Output類,則可以在任何可以傳遞給Q類中使用該方法。

當您想要使集合的行為與原始類相同時,第二個非常有用。 如果你拿B並且你創建了一個子類A ,那么你可以在任何預期B地方傳遞A 但是如果你收集一個BQ[B]集合 ,你是否可以總是傳入Q[A]而不是? 一般來說,沒有; 有些情況下這是錯誤的做法。 但你可以說通過使用+B (協方差; Q covaries - 跟隨 - 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() )

如您所見, List並不關心它是否包含動物或汽車 List的開發人員沒有強制執行,例如只有汽車可以進入列表。

另外:

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的協方差,List List[Dog] 被認為是 List[Animal] 的子類 如果List不變,它將無法工作。

現在進入類型邊界:

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

正如您所見, Barn是一個僅供動物使用的系列 這里沒有車。

我在研究這個問題時發現了這篇博文。 對Scala方差進行了更深入的解釋,包括其在范疇論中的理論基礎

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

對於我的理解:


第一個是參數類型綁定,在我們的例子中有一個上限和下限類型,它是一個“類型參數A,它是B的一個子類型(或B本身)。


第二個是類定義的方差注釋,在我們的例子中是B的協方差子類


Scala:+ Java :? 擴展T Covariant子類

斯卡拉: - Java :? super T Contravariant子類

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM