5

私はコードを持っています:

class A {
    override def toString = "object class A"
}

class B extends A {
    override def toString = "object class B"
}

class Cell[+T](init: T) {
    private[this] var current: T = init
    def get: T = current
    def set(x: T) { current = x }
}

val cB = new Cell[B](new B)
println(cB.get)
val cA: Cell[A] = cB
println(cA.get)

しかし、私は行にエラーがあります:def set(x: T) { current = x }

エラー:共変タイプTは、値x def set(x:T){current=x}のタイプTの反変位置で発生します

説明してください

4

2 に答える 2

5

タイプの反変位置は、(とりわけ)そのタイプのインスタンスをメソッドに渡すことを可能にする任意の位置です。したがって、すべてのメソッドパラメータタイプは反変の位置にあります。Tを共変(+T)として宣言したため、コンパイラはこれを許可しません。唯一のオプションは次のとおりです。

  • T不変にする
  • setメソッドを変更して、の新しいインスタンスを返し、Cell不変Cellになるようにします。
  • setメソッドを削除し、Cell不変にします

コンパイラーが実装時にsetメソッドを持つことを許可した場合、次のように記述できるため、型システムは安全ではなくなります。

val cs:Cell[String] = new Cell("")
val ca:Cell[Any] = cs
ca.set(5)
val s:String = cs.get //boom
于 2013-01-11T12:32:42.170 に答える
4

簡単に言えば、共変である可変コンテナを持つことはできないということです。これがコンパイルされたと仮定すると、あなたの例では、最後の2行は次のようになります。

val cA: Call[A] = cB
cA.set(new A)

Cell[B] aはCell[A]。の使用によるものであるため、最初の行は許可されます+T。そして、2行目も許可されます-もちろん、Cell[A]を保持するように設定できますA

しかし今、!ではなく、cB.getのインスタンスを返します。これは意味がなく、Cellの型パラメーターで共分散を許可しながら、この矛盾を解決する方法はありません。AB


より長く、より正式で包括的な回答については、次の質問を参照してください:Scala共変性/反変性

于 2013-01-11T12:35:09.237 に答える