2013-05-07 10 views
5

我已经了解到,Scala并未检查其方差位置的对象专用(private[this])或对象保护(protected[this])定义。为什么不检查它们是安全的?为什么不检查对象专用或对象保护定义的差异位置?

我已经阅读了一些与之相关的资料,但未能找到完整的答案。首先,Odersky的,等人的“编程在斯卡拉”说:

http://www.artima.com/pins1ed/type-parameterization.html#19.7

原来,访问来自定义它们不会引起变异的问题相同的对象变量。直观的解释是,为了构造方差会导致类型错误的情况,您需要引用一个包含对象的引用,该对象的静态类型比定义对象的类型要弱。

我不知道到底是什么,作者的意思是“一个对象”和“静态弱类型”。代码示例在这里更可取。

其次,“senia”在Scala Modifiers and Type parametrization中给出了一个很好的例子,它显示了类别私有(private)字段可能存在什么问题。 这个例子说服了我为什么应该检查类私有成员的差异性位置,但没有给出我们不必检查对象私有/受保护定义的原因的答案。我知道getOtherCache()这样的代码不能用对象专用字段写入。但是它并没有证明对象 - 私有/计划定义的无害性,我们没有编写一个程序,即对象 - 私有/计划定义导致方差问题。

三,Michid简要提及的话题,而decsribing如何实现在斯卡拉功能的memoization:

http://michid.wordpress.com/2009/02/23/function_mem/

class Memoize1[-T, +R](f: T => R) extends (T => R) { 
    ... 
    private[this] val vals = mutable.Map.empty[T, R] 
    ... 
} 

但是由于瓦尔斯从其仅包含实例访问,也不会引起问题有差异。

不幸的是,它不能回答我的问题:“与方差有关的访问控制是如何(或为什么)?”。

您能否更详细地解释不检查对象专用/受保护定义的方差位置(或提供一些参考)的基本原理?

回答

5

方差问题才发生一次的编译时和运行时的对象的类型而有所不同:

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引用不能在某处上传。 (我们总是完全知道我们的自我类型)。

所以,当我们回到Odersky的的话在这里,让我们一起来看看:

val cont: A[String] = new A[Any] { ... } 
cont.x // BAD! Is `Any`, not `String` 

cont是具有比与定义静态弱类型对象的引用,这就是为什么提到x是不允许。该指针不会发生这种上抛情况,因此以下是确定的:

trait B[-T] extends A[T] { 
    def foo() { 
    // here, this has always the most specific type. 
    val tmp: T = this.x 
    // do stuff 
    } 
} 
相关问题