Reputation: 191109
In Scala, I can use the parameter in subclass to the superclasses as follows:
abstract class A(var a:Int)
class B(a:Int) extends A(a)
class C(a:Int) extends B(a)
object Main extends App {
val b = new C(10)
println(b.a)
b.a = 100
println(b.a)
}
However, with case class, I have errors:
abstract class A(var a:Int)
class B(a:Int) extends A(a)
case class C(a:Int) extends B(a) // case generates a as val
object Main extends App {
val b = C(10)
println(b.a) // without val, a is not accessible
b.a = 100
println(b.a)
}
This is the message:
case_simple.scala:8: error: reassignment to val
b.a = 100
^
I see that it's caused by case class makes the constructor parameter immutable, but I have errors with C(var a:Int)
case_simple.scala:3: error: overriding variable a in class A of type Int;
variable a needs `override' modifier
case class C(var a:Int) extends B(a) // case generates a as val
^
one error found
And with C(override var a:Int)
case_simple.scala:3: error: overriding variable a in class A of type Int;
variable a cannot override a mutable variable
case class C(override var a:Int) extends B(a) // case generates a as val
How to solve this issue?
Upvotes: 3
Views: 2230
Reputation: 10882
1.
When you have construction like this:
abstract class A(var a: Int)
class B(a: Int) extends A(a)
a
in class B
is the constructor parameter that is passed to the parent constructor of A
. It can be rewritten as this for clarity:
abstract class A(var a: Int)
class B(param: Int) extends A(param)
param
is not a member of class B
, B
still has only one variable a
derived from class A
.
2.
In scala it is impossible to override var
. It seems that it doesn't make sense, but I can't find clear explanation.
Now to the point.
Case classes have special treatment for parameters. The syntax is limited, you can't define the parameter of case class that will not be the member of the class (either val
or var
). Taking into account two statements above, your only choice is to introduce another field in case class and then pass it to the parent constructor. It creates redundancy and is not good approach:
abstract class A(var a: Int)
class B(a: Int) extends A(a)
case class C(param: Int) extends B(param)
As a conclusion, I suggest you to avoid mixing case classes with vars. Case classes are designed to be small immutable DTOs. You can use copy
method of case class to conveniently change one or more fields while staying immutable:
case class C(a: Int)
val b = C(10)
println(b.a)
val b1 = b.copy(a = 100)
println(b1.a)
Upvotes: 1