如何在主构造函数中使用var子类化对象

时间:2009-11-17 09:57:32

标签: scala

我想做这样的事情:

class A (var updateCount: Int) {
}

class B (val name: String, var updateCount: Int) extends A(updateCount) {
  def inc(): Unit = {
    updateCount = updateCount + 1
  }
}

var b = new B("a", 10)
println(b.name)
println(b.updateCount)

b.updateCount = 9999
b.inc
println(b.updateCount)

但是编译器不喜欢它。

(fragment of extend.scala):5: error: error overriding variable updateCount in class A of type Int;
 variable updateCount needs `override' modifier
class B (val name: String, var updateCount: Int) extends A(updateCount) {

在updateCount上添加覆盖也不起作用。干净的方法是什么?

4 个答案:

答案 0 :(得分:7)

您不需要在子类构造函数签名中声明var

class B (val name: String, /* note no var */ updateCount: Int) extends A(updateCount) {
  //...
}

这也扩展到了构造函数中具有val s的类:

scala> class C(val i: Int)
defined class C

scala> class D(j: Int) extends C(j)
defined class D

答案 1 :(得分:4)

您需要避免为B声明标识符,以遮蔽为A声明的标识符。最简单的方法是选择一个不同的名称。但是,如果你真的真的不想这样做,可以选择以下方法:

class B (val name: String, updateCount: Int) extends A(updateCount) {
  self: A =>
  def inc(): Unit = {
    self.updateCount = self.updateCount + 1
  }
}

顺便说一下,从B声明中删除var

答案 2 :(得分:2)

当您在参数中使用var关键字时,这会使传入的值成为类中的新var。当你不这样做时,它使它成为一个构造函数参数(仅),并通过将它传递给构造函数来使用它的var值。所以人们给出的例子

class B(val name:String, updateCount:Int) extends A(updateCount)

是对的。

但是,scala使构造函数参数可以直接用于类中的方法(我不知道为什么),所以如果使用相同的名称,您会发现代码无法使用错误reassignment to val进行编译当你尝试重新分配“var”时。例如,在以下代码段中,不可变构造函数参数会隐藏继承的var,因此您无法分配参数。

class B (val name: String, updateCount: Int) extends A(updateCount) {
  def inc(): Unit = {
    updateCount = updateCount + 1
  }
}

答案 3 :(得分:0)

正如其他人所提到的,B中的构造函数参数遮蔽了超类的版本。这是有效的代码,不需要自我类型:

class A (var updateCount: Int) {
}

class B (val name: String, uc: Int) extends A(uc) {
  def inc(): Unit = {
    updateCount = updateCount + 1
  }
}