【发布时间】:2014-01-27 23:43:54
【问题描述】:
我遇到了一些与案例类和override protected val 相关的奇怪事情。
假设trait T 有一个受保护的def(或val)。
trait T {
protected def s: String
def print(): Unit = println(s)
}
我可以用val s 覆盖这个方法def s。没问题。
class A(override val s: String) extends T
好的。它编译。但这会使s 公开,因为没有受保护的关键字。
class B extends T {
override protected val s: String = "Show me the money"
}
好的。它编译。 (class B 的s 受到保护)
class C(override protected val s: String) extends T
好的。它编译。 (class C 的s 受保护)
让我们用case class 来做这些。
case class D(override val s: String) extends T
好的。它编译。 (虽然class D 的s 是公开的)
case class E() extends T {
override protected val s: String = "Show me the money"
}
好的。它编译。 (class E 的s 受到保护)
case class F(protected val s: String) extends T
好的。它编译。 (class F 的s 受到保护,并且s 也被覆盖,因为它在trait T 中并不具体。它是抽象的,所以override 关键字不是必需的。)
case class G(override protected val s: String) extends T
这里出现编译错误。
error: value s$1 overrides nothing
基本上,class F 和 class G 是相同的。 class F 覆盖 s 并且 s 受到保护。这可以通过F("Something").print() 确实会打印Something 来证明。
override protected val 可用于案例类,如 class E 所示。定义普通类C没有出错。
但是,仅定义 class G 会导致编译错误。
为什么会这样?
我使用的是 Scala 2.10.3
【问题讨论】:
-
似乎是一个错误。请举报here。
-
@sschaef 好的。我会报告的。
-
绝对是一个错误。因为
s是受保护的,所以scala 会生成一个单独的合成<caseaccessor> def s$1公共方法,该方法返回s,以便G的伴随对象可以访问它,例如。两者都被标记为override,即使s$1没有覆盖任何内容。 -
此外,案例类的受保护 val 参数实际上并没有任何用处:您可以使用提取器获取 val 的值,而无需成为子类。所以
s也可以公开。
标签: scala overriding protected