我了解到Scala不会检查对象私有(private[this])或对象保护(protected[this])定义的差异位置。为什么不检查它们是安全的?
我已经阅读了一些相关的资料,但还没有找到一个完整的答案。首先,Odersky等人的"Programming in Scala“说:
http://www.artima.com/pins1ed/type-parameterization.html#19.7
事实证明,从定义变量的同一对象访问变量不会导致方差问题。直观的解释是,为了构造方差将导致类型错误的情况,您需要具有对包含对象的引用,该对象的静态类型比定义该对象时使用的类型弱。
我不确定作者所说的“包含对象”和“静态弱类型”到底是什么意思。在这里,代码示例更可取。
其次,"senia“在Scala Modifiers and Type parametrization中给出了一个很好的例子,它展示了类私有(private)字段在方差方面可能会有什么问题。这个例子让我相信为什么应该检查类私有成员的变化位置,但没有回答为什么我们不需要检查对象私有/受保护的定义。我知道像getOtherCache()这样的代码不能用对象私有字段编写。但它并没有证明对象私有/投影定义的无伤大雅,因为我们没有编写一个程序,对象私有/投影定义会导致差异问题。
第三,Michid在描述如何在Scala中实现函数memoization时简要地提到了这个主题:
http://michid.wordpress.com/2009/02/23/function_mem/
class Memoize1-T, +R extends (T => R) { ...privatethis vals = mutable.Map.emptyT,R ... }
但是,由于vals只能从其包含的实例访问,因此它不会引起方差问题。
不幸的是,它没有回答我的问题“访问控制是如何(或为什么)与差异相关的?”
您能更详细地解释不检查对象私有/受保护定义的差异位置的原因吗(或提供一些参考资料)?
发布于 2013-05-08 07:11:11
只有当对象的编译时和运行时类型不同时,才会出现方差问题:
val a: List[Any] = List("foo"): List[String]在这里,a的静态类型(List[Any])比定义的(List[String])弱。此外,这同样适用于包含对象(即列表的元素)。(静态类型Any,定义类型String)。
如果我们有对象私有(或对象保护)字段,这种情况就不会发生:
trait A[-T] {
protected[this] val x: T
}当我们访问x时,我们可以确定它实际上是T类型,即使A是反向变量,因为this引用不能在某个地方向上转换。(我们总是完全了解我们的自我类型)。
所以,当我们回到奥德斯基的话,让我们来看看:
val cont: A[String] = new A[Any] { ... }
cont.x // BAD! Is `Any`, not `String`cont是对静态类型弱于使用定义的对象的引用,这就是不允许引用x的原因。这种向上转换的情况不会发生在This指针上,因此以下内容是可以的:
trait B[-T] extends A[T] {
def foo() {
// here, this has always the most specific type.
val tmp: T = this.x
// do stuff
}
}https://stackoverflow.com/questions/16428847
复制相似问题