Scala中不同的重写方法有什么区别?

pla*_*pus 12 overriding scala

Scala允许您以两种合法方式覆盖方法:

鉴于超级课程:

class A {
  def a = "A"
}
Run Code Online (Sandbox Code Playgroud)

我们可以通过以下方式覆盖方法"a":

class B extends A {
  override def a = "B"
}
Run Code Online (Sandbox Code Playgroud)

和

class B extends A {
  override def a() = "B"
}
Run Code Online (Sandbox Code Playgroud)

两者似乎都正确地覆盖了方法"a".这背后的设计决策是什么?为什么允许B中的"a()"覆盖A中的"a"?

Tra*_*own 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" }
Run Code Online (Sandbox Code Playgroud)

现在我们可以按预期编写以下内容:

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

scala> (new C).a
res1: java.lang.String = C
Run Code Online (Sandbox Code Playgroud)

还有这个:

scala> (new C).a()
res2: java.lang.String = C
Run Code Online (Sandbox Code Playgroud)

但不是这个:

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()
Run Code Online (Sandbox Code Playgroud)

因此Scala确实区分了两者,这显然必须反映在字节码中.假设我们编译以下内容:

class A { def a = "A" }
class B extends A { override def a = "B" }
Run Code Online (Sandbox Code Playgroud)

然后运行:

javap -verbose B > noArgList.txt
Run Code Online (Sandbox Code Playgroud)

然后将代码更改为:

class A { def a = "A" }
class B extends A { override def a() = "B" }
Run Code Online (Sandbox Code Playgroud)

重新编译,然后运行:

javap -verbose B > emptyArgList.txt
Run Code Online (Sandbox Code Playgroud)

最后检查差异:

<   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
Run Code Online (Sandbox Code Playgroud)

所以存在差异 - 两个版本的ScalaSignature注释具有不同的值.

至于为什么在Scala 2.0中进行了更改:规范指出它允许:

class C {
    override def toString: String = ...
}
Run Code Online (Sandbox Code Playgroud)

我的猜测是语言设计者只是没有理由要求用户记住在这种情况下使用被覆盖方法的方法.