12

Scala では、次の 2 つの正当な方法でメソッドをオーバーライドできます。

与えられたスーパークラス:

class A {
  def a = "A"
}

メソッド「a」を次のようにオーバーライドできます。

class B extends A {
  override def a = "B"
}

class B extends A {
  override def a() = "B"
}

どちらもメソッド「a」を正しくオーバーライドしているようです。この背後にある設計上の決定は何ですか? B の "a()" が A の "a" をオーバーライドできるのはなぜですか?

4

1 に答える 1

15

これは常に当てはまるとは限りません (言語仕様の変更ログから):

Scala バージョン 2.0 では、空のパラメーター リストに関するオーバーライドの規則も緩和されています。一致するメンバーの定義の改訂 (§5.1.3) により、明示的ではあるが空のパラメーター リスト()を持つメソッドをパラメーターなしのメソッドでオーバーライドすることが可能になり、その逆も可能になりました。

パラメーターなしのメソッドと空のパラメーター リストを持つメソッドとの間に観察可能な違いがあることを考えると、これは奇妙な設計上の決定のように思えることは間違いありません。たとえば、次のものがあるとします。

class A { def a = "A" }
class B extends A { override def a = "B" }
class C extends A { override def a() = "C" }

これで、予想どおり、次のように記述できます。

scala> (new B).a
res0: java.lang.String = B

scala> (new C).a
res1: java.lang.String = C

この:

scala> (new C).a()
res2: java.lang.String = C

しかし、これではありません:

scala> (new B).a()
<console>:10: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
              (new B).a()

そのため、Scala はこの 2 つを区別しており、これは明らかにバイトコードに反映されている必要があります。以下をコンパイルするとします。

class A { def a = "A" }
class B extends A { override def a = "B" }

そして実行します:

javap -verbose B > noArgList.txt

次に、コードを次のように変更します。

class A { def a = "A" }
class B extends A { override def a() = "B" }

再コンパイルして実行します。

javap -verbose B > emptyArgList.txt

最後に違いを確認します。

<   MD5 checksum 88aeebf57b645fce2b2fcd2f81acdbbd
---
>   MD5 checksum 3733b3e4181b4b2f4993503d4c05770e
32c32
<   #18 = Utf8               }1A!
                                 \t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg
jiz\"a\tAQ!BY\t!Y                                                  G.Y11bU2bY|%M[3di\")C%1A(
                 /A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r
---
>   #18 = Utf8               }1A!
                                 \t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg
jiz\"a\tAQ!BY\t!                                                   G.Y11bU2bY|%M[3di\")C%1A(
                /A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r

したがって、違いがあります。2 つのバージョンでは、ScalaSignature注釈の値が異なります。

Scala 2.0 で変更が行われた理由については、仕様では次のように記述されています。

class C {
    override def toString: String = ...
}

私の推測では、言語設計者は、このような場合にオーバーライドされたメソッドがどのアプローチを使用しているかをユーザーが覚えておく必要がある理由を理解していなかったのです。

于 2012-09-01T23:34:06.170 に答える