开发者

How to subclass an object with a var in its primary constructor

开发者 https://www.devze.com 2022-12-12 04:58 出处:网络
I\'m wanting to do something like this: class A (var updateCount: Int) { } class B (val name: String, var updateCount: Int) extends A(updateCount) {

I'm wanting to do something like this:

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)

but the compiler doesn't like it.

(fragment of extend.scala):5: error: erro开发者_Python百科r 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) {

Adding override on updateCount doesn't work either. What's the clean way to do this?


You don't need to declare the var in the subclass constructor signature:

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

This also extends to classes with vals in their constructors also:

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

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


You need to avoid having the identifier declared for B shadowing the identifier declared for A. The easiest way to do that is to chose a different name. If, however, you really, really don't want to do that, here is an alternative:

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

And, by the way, drop the var from B declaration.


When you use the var keyword in the parameters, this makes the value passed in be a new var in the class. When you don't do that, it makes it a constructor parameter (only), and you use it's value for the var by passing it to the constructor. So the example that people have given

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

is correct.

However, scala makes constructor parameters directly available to the methods in the class (I'm not sure why), so if you use the same name you will find that your code fails to compile with the error reassignment to val when you try to reassign the "var". For example in the following snippet, the immutable constructor parameter shadows the inherited var and so you can't assign to the parameter.

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


As others mention, your constructor param in B is shadowing the superclass' version. Here's the code that works and doesn't require self-type:

class A (var updateCount: Int) {
}

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

精彩评论

暂无评论...
验证码 换一张
取 消