В Scala, поля и методы принадлежат к одному и тому же пространству имен, поэтому поле может легко переопределить метод. Это очень привлекательная функция Scala. Например, это позволяет фиксировать метод класса к конкретной ссылкой на какой-то момент иерархии классов:Переопределение абстрактных методов со значениями, хорошая практика?
abstract class AC { def x: Int }
class C extends AC { override val x = 10 }
Предположим, что существует второй Base
«с атрибутом вычисляется форма x
:
abstract class AC { def x: Int; val y: Int = x*2 }
class C extends AC { override val x = 10 }
val v = (new C).y
Можно было бы ожидаю v
значение будет 20
но 0
. Хорошо, происходит то, что конструктор AC
вызывается до того, как C
, следовательно, x
(который теперь является атрибутом) еще не установлен в этой точке, а конструктор использует значение по умолчанию для целых чисел (может быть, неправильно).
Что меня поражает то, что с:
class C extends AC { override def x = 10 }
val v = (new C).y
v
равна 20.
У меня есть подозрение, что разница исходит из того факта, что методы разрешаются иначе, чем значения. Может ли кто-нибудь объяснить разницу в поведении? подробнее о том, как работают конструкторы Scala? Не было бы более согласованным иметь одинаковое поведение в обоих случаях?
Относительно названия вопроса: Не опасно ли переопределять методы как значения? Некоторый клиентский код мог бы сделать это для класса библиотеки, не заметив, что зависимые атрибуты могут получить недопустимые значения, тем самым генерируя ошибки.
Я думаю, что лучшей практикой было бы сделать 'y' ленивым или def, когда он ссылается на то, что может быть отменено. Хотя я не уверен, почему вторая инициализация имеет проблемы. Трудно найти что-либо в спецификации о том, как обрабатывать def с помощью val. –