Ответ 1
В Scala, когда вы пишете var foo
, компилятор Scala автоматически генерирует сеттер (называемый foo_=
) и getter (называемый foo
) для него и устанавливает это поле как личное ( вы увидите его закрытым, если вы декомпилируете класс с "общедоступными" Scala полями с javap
). То, что означает "метод foo_ = переопределяет ничего", означает ошибку. В вашей характеристике вы не определили метод foo_=
, а для публичного поля setter и getters всегда попадают парами.
Если вы не указали значение по умолчанию в признаке (т.е. абстрактный метод), то ключевое слово override
не требуется. Поэтому в вашем первом примере геттер переопределяет абстрактный метод и сеттер... он просто есть. Компилятор не жалуется. Но когда вы предоставляете фактическую реализацию метода в признаке, вам нужно специально написать ключевое слово override
при переопределении. При написании protected var foo
вы не указали ключевое слово override
для получателя, а при записи override protected var foo
вы также указали компилятору, что метод foo_=
должен быть переопределен, но этот признак не имеет такого метода.
Кроме того, логически вы не можете переопределить def
с помощью var
(учитывая строгий обзор переопределения, как в предыдущем абзаце). A def
логически является функцией (вы даете ей некоторый ввод, она производит вывод). A var
похож на функцию no-arg, но также поддерживает установку его значения на что-то еще, операцию, которая не поддерживается функцией. Вместо этого, если вы измените его на val
, все будет в порядке. Он похож на функцию, которая всегда производит тот же (кешированный) результат.
Если вы хотите иметь подобное поведение с var
, вы можете сделать что-то вроде этого (с помощью явного setter и getters):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Теперь вы можете делать все, что вы можете сделать с var:).
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"