5

この関数がコンパイルされないのはなぜですか?

case class MyType(n: Int)
def intersection(s1: Set[MyType], s2: Set[_ <: MyType]) =
  (s1 & s2)

次のエラーが表示されます。

エラー: タイプが一致しません。found : Set[_$1] where type _$1 <: MyType 必須: scala.collection.GenSet[MyType] 注: _$1 <: MyType ですが、特性 GenSet は型 A で不変です。として_ <: MyType。(SLS 3.2.10) (w & r)

asInstanceOf を使用せずに Set[MyType] 型に 2 番目の引数を「昇格」する簡単な方法はありますか?

4

3 に答える 3

3

Setと定義されているからですSet[A]インバリアントであり、コバリアントではありません。

&と定義されている

def &(that: GenSet[A]): Set[A]

タイプ の引数が必要ですSet[A]。しかし、代わりに提供していSet[_ <: MyType]ます。

Set[_ <: Mytype]は共変Set[MyType]です。しかし、宣言では、引数は不変である必要があると述べているSet[MyType]ため、エラーが発生します。

PS: 共分散は、狭いものから広いものへの型変換と考えることができます。例: if DogextendsAnimalと if you doAnimal a = new Dog()の場合、Dog (狭い) が Animal (広い) に変換されます。その上では、不変型が期待されます。つまりAnimal、 が必要な場合は、 のみを提供できますAnimal。もう 1 つの例はjava.util.ArrayList、インバリアントです。

于 2013-08-02T07:53:48.640 に答える
2

Setは不変ですが、驚くほど簡単な回避策があります。

def intersection(s1: Set[MyType], s2: Set[_ <: MyType]) =
  s2 filter s1

または、結果の型の型推論を改善したい場合は、次のようにします。

def intersection[X <: MyType](s1: Set[MyType], s2: Set[X]): Set[X] =
  s2 filter s1

ここでs1は関数として使用されます。関数は引数が反変であるためs1.apply、型(MyType) => Booleanは として受け入れられ(_ <: MyType) => Booleanます。

の実装方法と同様にintersect、パフォーマンスは と同じです。this filter thatintersectSet

于 2017-10-09T12:47:50.017 に答える