Ответ 1
Это не всегда было так (из журнала изменений спецификация языка):
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 делает различие между этими двумя, что, очевидно, должно отразиться на байт-коде. Предположим, что мы скомпилируем следующее:
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
.
Что касается изменения в Scala 2.0: спецификация отмечает, что это позволяет:
class C {
override def toString: String = ...
}
Я предполагаю, что разработчики языка просто не увидели причины, по которым пользователи должны были помнить, какой подход использует переопределенные методы, используемые в таких случаях.