11

Scala の共変性と反変性の実世界の例に触発されて、より良い質問は次のようになると思いました。

ライブラリを設計するときに、型パラメーターを共変にするか反変にするかを決定する際に自問すべき特定の質問のセットはありますか? それとも、すべてを不変にしてから、必要に応じて変更する必要がありますか?

4

1 に答える 1

16

簡単ですが、意味はありますか?Liskov 置換を考えてみてください。

共分散

の場合、aが期待される場所に aA <: Bを渡すのは理にかなっていますか? もしそうなら、それを作ってください。古典的な例は immutableであり、 aが のサブタイプであると想定して、 a を期待するものに a を渡すことができます。C[A]C[B]C[+T]ListList[A]List[B]AB

2 つの反例:

ミュータブル シーケンスは不変です。それ以外の場合はタイプ セーフ違反が発生する可能性があるからです (実際、Java の共変Arrayはまさにそのようなことに対して脆弱であり、Scala で不変なのはそのためです)。

Setそのメソッドは immutable のメソッドと非常に似ていますが、Immutableは不変Seqです。違いはcontains、セットでは型付けされ、シーケンスでは型付けされない (つまり、 accept Any) にあります。そのため、他の方法で共変にすることは可能ですが、特定のメソッドで型の安全性を高めたいという要望により、共分散よりも不変性を選択することになりました。

反分散

の場合、aが期待される場所に aA <: Bを渡すのは理にかなっていますか? もしそうなら、それを作ってください。典型的な例は. いくつかの無関係な技術的問題が反変になることを妨げていますが、直観的には のスーパークラスを注文できるものは も注文できます。のスーパータイプである タイプ のすべての要素を注文するは、 を期待するものに渡すことができます。C[B]C[A]C[-T]OrderingOrderingAAOrdering[B]BAOrdering[A]

Scala の順序は反Ordering変ではありませんが、ScalazOrderは予想どおり反変です。Scalaz のもう 1 つの例は、そのEqualトレイトです。

混合分散?

Scala における混合分散の最もわかりやすい例はFunction1(および 2、3 など) です。それが受け取るパラメータでは反変であり、それが返すものでは共変です。ただし、これFunction1は多くのクロージャーに使用されるものであり、クロージャーは多くの場所で使用されることに注意してください。これらの場所は通常、Java が単一抽象メソッド クラスを使用する (または使用する予定である) 場所です。

したがって、SAM クラスが適用される状況では、反分散と共分散が混在する可能性があります。

于 2011-03-12T01:10:21.337 に答える