Почему я не могу назначить var в подкласс Scala?
Предположим, что у меня есть следующий абстрактный класс:
abstract class A (var is_happy : Boolean) {
def toggle_happiness();
}
И теперь я хочу определить конкретный класс, который реализует метод toggle_happiness()
:
class B (is_happy : Boolean) extends A (is_happy) {
def toggle_happiness() = {
is_happy = !is_happy
}
}
Scala компилятор дает мне:
error: reassignment to val
is_happy = !is_happy
^
Что здесь происходит? Я думал, что is_happy
ссылается на var
в моем классе, который задается моим конструктором. У меня конфликт с именем is_happy
?
Спасибо,
Dan
Ответы
Ответ 1
См. этот вопрос. По сути, Scala считает, что вы пытаетесь назначить параметр конструктора is_happy
, а не var
, is_happy
, который, как раз, имеет одно и то же имя. Некоторые решения заключаются в следующем:
- Сделайте реферат
var
в базовом классе.
- Переименуйте параметр конструктора (например,
_is_happy
). Поскольку имена параметров являются частью общедоступного API ваших конструкторов/методов, это может нецелесообразно.
Вам повезло, что проблема была обнаружена во время компиляции в вашем случае. Эта проблема может привести к очень удивительному поведению во время выполнения, когда оно не обнаружено.
Ответ 2
Существует еще одно простое решение. Тот, который требует только изменить B
(не нужно менять базовый класс) и не будет изменять интерфейс (без переименования параметров).
Просто введите частный метод, который возвращает это, и явно разыщите это:
class B (var is_happy : Boolean) extends A {
private def self = this
def toggle_happiness() = {
self.is_happy = !self.is_happy
}
}
Обратите внимание, что эта работа локализована в B
. Всюду (включая производные классы) вы можете использовать только is_happy
(нет необходимости в self.is_happy
).
В качестве побочного примечания мы должны действительно иметь возможность прямого разыменования this
, как в this.is_happy
(вместо добавления метода self
и выполнения self.is_happy
). Но по какой-то причине компилятор будет слепо трактовать this.is_happy
так же, как is_happy
, поэтому мы вернемся к квадрату, а this.is_happy
на самом деле все еще укажем на параметр B
, а не на переменную A
. Это очень похоже на ошибку компилятора.