12

private finalScalaの修飾子は何に使用できますか?

以下のコードが与えられます:

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

bar of B実際には2つのfoo定義があり、Bの後者がAの前者をオーバーライドしないため、 2行目が印刷されない理由は理解できます。そうでない場合、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)
}

これは、コンパイラによって提供されるエラーの 1 つです: 「メソッド foo は最終メンバーをオーバーライドできません」

それではどうぞ。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 に答える