假设我有以下抽象类:
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
冲突?
谢谢, 丹
答案 0 :(得分:14)
见this question。从本质上讲,Scala认为您正在尝试分配构造函数参数is_happy
,而不是恰好具有相同名称的var
,is_happy
。一些解决方案是:
var
摘要。_is_happy
)。由于参数名称是构造函数/方法的公共API的一部分,因此这可能是不可取的。您很幸运,在您的情况下,在编译时检测到问题。此问题可能导致very surprising runtime behavior when it goes undetected。
答案 1 :(得分:0)
还有另一个简单的解决方案。一个只需要修改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
相同,所以我们回到原点1而this.is_happy
实际上仍然指向B
的参数而不是A
的变量。这对我来说非常像编译错误。