共変タイプAは、値aのタイプAの反変位置で発生します



Covariant Type Occurs Contravariant Position Type Value



解決:

エラーメッセージは、理解すれば実際には非常に明確です。一緒に行きましょう。

あなたはクラスを宣言していますタイプパラメータの共変としてのボックスA.これは、どのタイプでもX拡張A(つまりNS<: A), Box [X]は、ボックス[A]。



明確な例を示すために、動物の種類:

封印された抽象クラス動物のケースクラス猫は動物のケースクラスを拡張します犬は動物を拡張します

あなたが定義する場合犬<: Animal and ネコ<: Animal, then both ボックス[犬]とBox [Cat]は次のように見ることができますボックス[動物]とあなたは例えばすることができます両方のタイプを含む単一のコレクションを作成し、Box [動物]タイプ。



このプロパティは非常に便利な場合もありますが、使用できる操作に制約も課します。箱。これが、コンパイラが定義を許可しない理由です。defセット。

定義を許可する場合

def set(a:A):単位

その場合、次のコードが有効です。



val catBox = new Box [Cat] val animalBox:Box [Animal] = catBox // `Cat<: Animal` val dog = new Dog animalBox.set(dog) // This is non-sensical!  

最後の行は明らかに問題です。catBoxには、犬!メソッドの引数は、共分散の反対である「反変位置」と呼ばれるものに現れます。確かに、あなたが定義する場合ボックス[-A]、次にネコ<: Animal implies Box [Cat]>:Box [Animal](Box [Cat]はのスーパータイプですボックス[動物])。私たちの例では、これはもちろん無意味です。

あなたの問題に対する一つの解決策は、ボックスクラスは不変です(つまり、コンテンツを変更する方法を提供しませんボックス)、代わりに、で定義されている適用メソッドを使用します新しいボックスを作成するためのケースクラスコンパニオン。必要に応じて、定義することもできますローカルに設定し、外部に公開しないでくださいとして宣言することによるボックスprivate [this]。コンパイラはこれを許可します。private [this]は、障害のある例の最後の行がコンパイルされないことを保証します。setメソッドは、の特定のインスタンスの外部では完全に見えません。箱。


他の人は、コードがコンパイルされない理由についてすでに答えを出しましたが、コードをコンパイルする方法についての解決策を与えていません。

>ケースクラスBox [+ A](v:A){def set [B>:A](a:B)= Box(a)}定義されたクラスBox> trait Animal;ケースクラスCat()は動物定義の特性を拡張します動物定義クラスCat> Box(Cat())。set(new Animal {})res4:Box [Animal] = Box([email protected])> Box [Cat](Cat( ))。set [Animal](new Animal {})res5:Box [Animal] = Box([email protected])

タイプ引数B>:Aは、必要に応じてスーパータイプを推測するようにコンパイラーに指示する下限です。例でわかるように、動物は次の場合に推測されます猫が与えられます。


他の答えに加えて、私は別のアプローチを提供したいと思います:

def set [B>:A](x:B):Box [B] = Box(x)