Проблема с геттером/сеттерами Scala
в настоящее время я изучаю Scala и только что обнаружил способ создания пользовательских геттеров/сеттеров полей. У меня есть простой пример работы:
class Thing(private val a:Int){
override def toString = "Thing[" + a + "]"
private var _value = a
def value = _value
def value_= (newVal:Int) = _value = newVal
}
на консоли я могу сделать:
scala> var t = new Thing(2)
t: dylan.code.Thing = Thing[2]
scala> t.value
res1: Int = 2
scala> t.value = 3
scala> t.value
res2: Int = 3
теперь я пытаюсь привести эту концепцию к немного более сложному примеру; я попытаюсь сократить код до того, что актуально:
abstract class CellExpression[Type] extends Publisher[CellUpdateEvent[Type]] with Subscriber[CellUpdateEvent[Type], CellExpression[Type]]{
protected var cachedValue: Type = recalculateValue()
protected def recalculateValue(): Type
protected def changeValue(newValue: Type):Unit = {
val oldValue = value()
if(newValue != oldValue){
cachedValue = newValue
publish(new CellUpdateEvent(this, oldValue, newValue))
}
}
def value() = cachedValue
def notify(pub: CellExpression[Type], event: CellUpdateEvent[Type]) = changeValue(recalculateValue())
}
//....
class CellVariable[Type](private val initialValue:Type) extends CellExpression[Type]{
cachedValue = initialValue
protected def recalculateValue() = { cachedValue }
override def toString = "CellVariable[" + value + "]"
def value_= (newValue:Type) = {changeValue(newValue)}
}
насколько я могу судить, я сделал то, что мне нужно, чтобы иметь возможность treate value
как поле через свой геттер и сеттер. Но когда я пробую это в консоли, я получаю:
scala> var i = new CellVariable(2)
i: dylan.code.CellVariable[Int] = CellVariable[2]
scala> i.value = 3
<console>:11: error: reassignment to val
i.value = 3
^
что я сделал неправильно и как я могу это исправить?
2 ответов
Я действительно наткнулся на решение.
строка, в которой я объявляю свою функцию значения:def value() = cachedValue
виновник.
Если я удалю скобки, чтобы сделать строку def value = cachedValue
все работает так, как я ожидал.
вы не можете изменить значения в Scala. Значение присваивается один и только один раз. Если вы хотите это сделать, вам нужно использовать переменные вместо значений. Другими словами, измените объявление с val
до var
.
проблема в одном из ваших определений классов и может быть на линии без val
потому что я считаю, что если вы пренебрегаете объявлением имени, то Scala предполагает, что это значение и поэтому неизменяемо.
не уверен, что вы хотите получить и сеттеры для этого. Scala позволяет игнорировать все эти накладные расходы Java.
вероятно, это строка, которая говорит cachedValue = initialValue
потому что он не объявлен с var
в любом месте этого класса. Определение в другом классе-это другое имя, потому что оно находится в другой области. Тебе придется сказать что-то вроде "класс".varname для изменения переменной, определенной в другом классе.