違いは何ですか
[A <: B]
そして
[+B]
scalaでは?
Q[A <: B]
は、クラスQ
がA
のサブクラスである任意のクラスB
を取ることができることを意味します。
Q[+B]
は、Q
がanyクラスを取ることができることを意味しますが、A
がB
のサブクラスの場合、Q[A]
はQ[B]
のサブクラスと見なされます。
Q[+A <: B]
は、クラスQ
がB
のサブクラスのみを受け取り、サブクラスの関係を伝播できることを意味します。
1つ目は、一般的なことをしたいが、B
の特定のメソッドセットに依存する必要がある場合に便利です。たとえば、Output
クラスにtoFile
メソッドが含まれている場合、Q
に渡すことができる任意のクラスでそのメソッドを使用できます。
2番目は、元のクラスと同じように動作するコレクションを作成する場合に便利です。 B
を受け取り、サブクラスA
を作成すると、A
が必要な場所であればどこでもB
を渡すことができます。しかし、B
、Q[B]
の-collectionを取る場合、代わりに常にQ[A]
を渡すことができるのは本当ですか?一般に、いいえ。これが不適切な場合があります。しかし、これは+B
(共分散; Q
共変----B
のサブクラスの継承関係に従う)を使用して行うのが正しいことであると言えます。
私は拡張したいと思います レックスカーの素晴らしい答え いくつかの例を挙げてみましょう:4つのクラスがあるとしましょう:
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には、動物または車が含まれているかどうかは関係ありません。リストの開発者はそれを強制しませんでした。車のみがリスト内に入ることができます。
さらに:
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())
^
*/
ご覧のように納屋は、動物のみを対象としたコレクションです。ここには車は入れません。
この質問を調査しているときに、このブログ投稿を見つけました。 Scala分散のカテゴリー理論における理論的根拠を含む)のさらに深い説明を与える
http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/
私の理解のために:
1つ目はパラメータタイプの境界です。この場合、上限と下限のタイプ境界は「BのサブタイプであるタイプパラメータA(またはB自体)」です。
2つ目は、クラス定義の分散アノテーションです。この例では、Bの共分散サブクラス化です。
Scala:+ Java:? T共変サブクラスを拡張します
Scala:-Java:?スーパーT反変サブクラス化