13

私はメモ化クラスを作成しています。

各クラスは関数型を記憶し、次の定義を持ちます。

 class MemoizedFunction1[-T1, +R](f: T1 => R) {
    private[this] val cache = mutable.Map[T1, R]()
    def apply(t: T1): R = cache.getOrElseUpdate(t,f(t))
  }

これはうまくコンパイルされ、期待どおりに動作します。ただし、変更を削除するとprivate[this]、次のエラーが発生します。

contravariant type T1 occurs in invariant position in type => scala.collection.mutable.Map[T1,R] of value cache

修飾子を削除すると、突然反変型 T1 が Map の不変型に干渉するのはなぜですか? 修飾子は型のパラメーター化にどのように影響しますか?

4

3 に答える 3

7

を削除できるとしましょう[this]

あなたなし[this]でメソッドを追加することができますgetOtherCache

class MemoizedFunction1[-T1, +R](f: T1 => R) { 
  private val cache = mutable.Map[T1, R]() // trait Map[A, B] extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]]
  def apply(t: T1): R = cache.getOrElseUpdate(t,f(t))

  def getOtherCache(other: MemoizedFunction1[T1, R]) {
    val otherCache: mutable.Map[T1, R] = other.cache;
  }
}

class A
class B extends A

val mf1: MemoizedFunction1[B, B] = new MemoizedFunction1[B, B](b => b)

val mf2: MemoizedFunction1[B, B] = new MemoizedFunction1[A, B](a => new B)
// mf2 is MemoizedFunction1[B, B]
// mf2 contains mutable.Map[A, B]

mf1.getOtherCache(mf2) //Error! mf2.cache is NOT mutable.Map[B, B]!
于 2012-04-07T07:09:03.083 に答える
6

すべてを理解しているわけではありませんが、45 ページのScala 言語仕様 2.9のセクション 4.5 (Variance Annotations) で対処されています。

クラスのオブジェクト プライベートまたはオブジェクト保護された値、変数、またはメソッド (§5.2) の型パラメーターへの参照は、それらの分散位置についてチェックされません。これらのメンバーでは、型パラメーターは、法的な差異の注釈を制限することなく、どこにでも表示できます。

仕様によると、例を単純化するために、これで問題ありません。

class Inv[T]

class Foo[-T] {
  private[this]   val a: Inv[T] = sys.error("compiles")
  protected[this] val b: Inv[T] = sys.error("compiles")
}

しかし、あなたが削除すると、[this]それは文句を言うでしょう。オブジェクトが非公開または保護されていない場合、反変の戻り値の型がオブジェクトの外に漏れて実行時エラーが発生する可能性があるため、あるレベルでは理にかなっています。

于 2012-04-07T04:56:41.397 に答える
2

Scala でのプログラミングでは、セクション19.7 オブジェクト プライベート データでこのトピックに触れています。分散の問題を引き起こします。」

于 2012-04-07T11:19:25.987 に答える