为什么我不能在Scala子类中赋值给var?

时间:2011-07-11 21:31:49

标签: scala inheritance constructor

假设我有以下抽象类:

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冲突?

谢谢, 丹

2 个答案:

答案 0 :(得分:14)

this question。从本质上讲,Scala认为您正在尝试分配构造函数参数is_happy,而不是恰好具有相同名称的varis_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的变量。这对我来说非常像编译错误。