我正在创建一个memoization类.
每个类都会记忆一个函数类型,并具有以下定义:
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))
}
Run Code Online (Sandbox Code Playgroud)
这很好地编译并按预期工作.但是,如果我删除修改后的private[this]我得到以下错误:
contravariant type T1 occurs in invariant position in type => scala.collection.mutable.Map[T1,R] of value cache
Run Code Online (Sandbox Code Playgroud)
为什么当我删除修饰符时,逆变类型T1会突然干扰地图的不变类型?修饰符如何影响类型参数化?
并不是我理解所有这些,但这在第45页的Scala语言规范2.9的 4.5节(方差注释)中得到了解决.
不检查对类的对象 - 私有或对象保护的值,变量或方法(第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")
}
Run Code Online (Sandbox Code Playgroud)
但如果你删除[this]它会抱怨.在某种程度上它是有意义的,因为如果它不是对象私有或受保护,逆变返回类型可能泄漏到对象外部并导致运行时错误.
我们假设你可以删除[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]!
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
622 次 |
| 最近记录: |