[英]What's the difference between A<:B and +B in Scala?
有什么區別
[A <: B]
和
[+B]
在斯卡拉?
Q[A <: B]
表示類Q
可以接受任何作為B
的子類的A
類。
Q[+B]
表示Q
可以取任何類,但如果A
是B
的子類,則Q[A]
被認為是Q[B]
的子類。
Q[+A <: B]
意味着類Q
只能獲取B
的子類以及傳播子類關系。
當你想要做一些通用的東西時,第一個是有用的,但你需要依賴B
的某些方法。 例如,如果您有一個帶有toFile
方法的Output
類,則可以在任何可以傳遞給Q
類中使用該方法。
當您想要使集合的行為與原始類相同時,第二個非常有用。 如果你拿B
並且你創建了一個子類A
,那么你可以在任何預期B
地方傳遞A
但是如果你收集一個B
, Q[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.