Вопрос по override, scala – В чем разница между различными переопределенными методами в Scala?

12

Scala позволяет переопределить метод двумя законными способами:

Данный супер класс:

class A {
  def a = "A"
}

Мы можем переопределить метод & quot; a & quot; от:

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

а также

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

оба, похоже, переопределяют метод "a" правильно. Какое дизайнерское решение стоит за этим? Зачем использовать & quot; a () & quot; в B, чтобы переопределить "a" в?

a() а такжеa оба метода названыa которые не принимают аргументов, т. е. имеют нулевую арность, то есть они идентичны. Почему бы им этого не позволить? oldrinb

Ваш Ответ

1   ответ
15

Это не всегда имело место (из журнала измененийспецификация языка):

Scala version 2.0 also relaxes the rules of overriding with respect to empty parameter lists. The revised definition of matching members (§5.1.3) makes it now possible to override a method with an explicit, but empty parameter list () with a parameterless method, and vice versa.

Вы правы, что это кажется странным дизайнерским решением, учитывая, что наблюдаются различия между методами без параметров и с пустыми списками параметров. Например, предположим, у вас есть следующее:

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 делает различие между ними, что, очевидно, должно быть отражено в байт-коде. Предположим, мы скомпилировали следующее:

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

Таким образом, существует различие - две версии имеют разные значения дляScalaSignature аннотаций.

Относительноwhy изменение было сделано в Scala 2.0: спецификация отмечает, что это позволяет:

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

Я предполагаю, что разработчики языка просто не видели причины требовать от пользователей запоминать, какой подход используется в переопределенных методах, используемых в подобных случаях.

Это довольно низкоуровневая деталь реализации, о которой вам не нужно долго беспокоиться,if ever, Его роль - позволить компилятору Scala проводить подобные различия.
Поскольку я только начинаю изучать Scala, не могли бы вы рассказать, для чего используется аннотация ScalaSignature? platypus

Похожие вопросы