views:

145

answers:

2

Short of renaming the constructor parameter in the primary constructor of class B, what change can I make to the following code (without changing its function) so that Scala will compile it successfully?

Example:

class A(var a: Int)
class B(a: Int) extends A(a) {
  def inc(value: Int) { this.a += value }
}

Error:

$ scala construct.scala
construct.scala:3: error: reassignment to val
  def inc(value: Int) { this.a += value }
                               ^
one error found

I raised this question in an answer to my previous question, "In Scala, how do you define a local parameter in the primary constructor of a class?".

+5  A: 
class A(var a: Int)
class B(a: Int) extends A(a) {
  def inc(value: Int) { (this: A).a += value }
}
Mitch Blevins
Nice! The type cast `(this: A)` is new to me!
Derek Mahar
Me, too. Daniel Sobral introduced me to it recently. http://stackoverflow.com/users/53013/daniel
Mitch Blevins
Note that this is a type-safe upcast, unlike (this.asInstanceOf[A]).a, which would have also compiled.
Mitch Blevins
Cool. Now I know a little further (http://stackoverflow.com/questions/1889454/in-scala-how-do-you-define-a-local-parameter-in-the-primary-constructor-of-a-cla).
Randall Schulz
Note: `(this: A)` is technically referred to as "type ascription" (http://davetron5000.github.com/scala-style/types/ascription.html).
Randall Schulz
A: 

Another alternative:

class A(var a: Int)
class B(a: Int) extends A(a) {
  self: A => 
  def inc(value: Int) { self.a += value }
}

This might work better for more extensive cases, as you can use self (or whatever other name you choose) throughout the body of the function.

Daniel
This compiles, but is not correct.val x = new B(1); x.inc(5); println(x.a) // == 1
Mitch Blevins
Daniel, I guess you mistaken a little bit: you are making an anonymous function (A) => Unit in `inc` and don't return it, as inc's return type is Unit. So no increment happens. Obviously, `self: A =>` should be after class B's opening brace.
Alexander Azarov
You are both correct, my mistake. I have moved the `self: A =>` statement to the proper place.
Daniel