12

我可以private final在 Scala 中使用修饰符做什么?

鉴于以下代码:

1| class A { def callFoo = foo; private final def foo = "bar of A" }
2| class B extends A { private final def foo = "bar of B"}
3| println((new A()).callFoo)
4| println((new B()).callFoo)

第 3 行和第 4 行打印:

1| bar of A
2| bar of A

可以理解为什么第 2 行不打印bar of B,因为实际上有两个foo定义,而 B 中的后者不会覆盖 A 中的前者。否则 Scala 将需要override- 而不是final修饰符。

那么为什么 Scala 不简单地禁止修饰符的组合private final呢?

4

3 回答 3

14

好的,这很棘手。您的问题:“那么为什么 Scala 不简单地禁止修饰符 private final 的组合?” 是基于这种组合没有用的假设。

假设你是对的(你是对的,除了一个小细节,稍后会提到)。我不是编译器,但从我的角度来看,“简单禁止”可能根本没有那么简单(至少在这种情况下)。为什么有人会尝试这样做?有哪些取舍?仅仅因为某些东西没有用并不一定意味着它会造成任何伤害。只是不要使用它...

现在,您似乎忽略了一个微小的细节。private修饰符是可见性修饰符,这意味着不class B知道它的存在。但是 Scala 的可见性修饰符比 Java 的要复杂一些。让我们假设无论出于何种原因您需要以下代码片段中显示的代码,编译器都不允许这样做。

package scope

class A {
  def callFoo = foo;
  private[scope] final def foo = "bar of A"
}
class B extends A {
  private[scope] final def foo = "bar of B"
}

object Main extends App {
  println((new A()).callFoo)
  println((new B()).callFoo)
}

这是编译器提供的错误之一:“method foo cannot override final member”

所以给你。Scala 只是禁止这种组合;)

于 2011-09-06T12:21:17.637 回答
4

解决更广泛的问题,

那么为什么 Scala 不简单地禁止修饰符 private final 的组合呢?

这是一个新规则,而且,一个新的例外。它使语言更加复杂,而且绝对没有任何好处。为什么无缘无故地让事情变得更复杂?

这就是 Java 所做的 Odersky 非常不喜欢的事情。为了使语言变得更复杂,必须有一些收获。

于 2011-09-06T13:57:21.943 回答
3

我最初认为这是为了防止在嵌套类中覆盖私有方法,但显然不是:

class A {
  private final def foo = 0

  class B extends A {
    override def foo = 1
  }
}

error: method foo overrides nothing
           override def foo = 1
                        ^

也许只是为了简化重构?所以如果你有一个final方法,试着去做private,发现你根本不需要它private,你会不会final在这个过程中失去自我?

于 2011-09-06T10:26:04.210 回答