Scala の共変性と反変性の実世界の例に触発されて、より良い質問は次のようになると思いました。
ライブラリを設計するときに、型パラメーターを共変にするか反変にするかを決定する際に自問すべき特定の質問のセットはありますか? それとも、すべてを不変にしてから、必要に応じて変更する必要がありますか?
Scala の共変性と反変性の実世界の例に触発されて、より良い質問は次のようになると思いました。
ライブラリを設計するときに、型パラメーターを共変にするか反変にするかを決定する際に自問すべき特定の質問のセットはありますか? それとも、すべてを不変にしてから、必要に応じて変更する必要がありますか?
簡単ですが、意味はありますか?Liskov 置換を考えてみてください。
の場合、aが期待される場所に aA <: B
を渡すのは理にかなっていますか? もしそうなら、それを作ってください。古典的な例は immutableであり、 aが のサブタイプであると想定して、 a を期待するものに a を渡すことができます。C[A]
C[B]
C[+T]
List
List[A]
List[B]
A
B
2 つの反例:
ミュータブル シーケンスは不変です。それ以外の場合はタイプ セーフ違反が発生する可能性があるからです (実際、Java の共変Array
はまさにそのようなことに対して脆弱であり、Scala で不変なのはそのためです)。
Set
そのメソッドは immutable のメソッドと非常に似ていますが、Immutableは不変Seq
です。違いはcontains
、セットでは型付けされ、シーケンスでは型付けされない (つまり、 accept Any
) にあります。そのため、他の方法で共変にすることは可能ですが、特定のメソッドで型の安全性を高めたいという要望により、共分散よりも不変性を選択することになりました。
の場合、aが期待される場所に aA <: B
を渡すのは理にかなっていますか? もしそうなら、それを作ってください。典型的な例は. いくつかの無関係な技術的問題が反変になることを妨げていますが、直観的には のスーパークラスを注文できるものは も注文できます。のスーパータイプである タイプ のすべての要素を注文するは、 を期待するものに渡すことができます。C[B]
C[A]
C[-T]
Ordering
Ordering
A
A
Ordering[B]
B
A
Ordering[A]
Scala の順序は反Ordering
変ではありませんが、ScalazのOrderは予想どおり反変です。Scalaz のもう 1 つの例は、そのEqualトレイトです。
Scala における混合分散の最もわかりやすい例はFunction1
(および 2、3 など) です。それが受け取るパラメータでは反変であり、それが返すものでは共変です。ただし、これFunction1
は多くのクロージャーに使用されるものであり、クロージャーは多くの場所で使用されることに注意してください。これらの場所は通常、Java が単一抽象メソッド クラスを使用する (または使用する予定である) 場所です。
したがって、SAM クラスが適用される状況では、反分散と共分散が混在する可能性があります。