Robo
Robo

Reputation: 4706

How to initialize parent case class parameters in constructor

the following code works as intended:

scala> case class Family(numPeople: Int)
defined class Family

scala> class MyFamily(val numBoys: Int, val numGirls: Int) extends Family(numBoys + numGirls)
defined class MyFamily

scala> val f = new MyFamily(2, 3)
f: MyFamily = Family(5)

scala> f.numPeople
res5: Int = 5

But what if the numBoys + numGirls part is more complex and takes several lines, is there some tidy way to set the numPeople value later? I tried doing this, but the Family(0) part looks wrong:

scala> class MyComplexFamily(val numBoys: Int, val numGirls: Int) extends Family(0) {
     | override val numPeople = numBoys + numGirls
     | }
defined class MyComplexFamily

scala> val f3 = new MyComplexFamily(3, 4)
f3: MyComplexFamily = Family(7)

Upvotes: 0

Views: 558

Answers (1)

Sergey
Sergey

Reputation: 2900

Case class inheritance is, though possible, discouraged - scala compiler generates equals and hashCode methods for case classes, and if you ever intend to be able to distinguish between a MyComplexFamily(3, 4) and Family(7), you're in trouble.

If, however, the only reason for that MyComplexFamily to exist is to perform some processing of input data, the preferred approach would be to define alternative constructor in the companion object of the case class.

case class Family(numPeople: Int)
object Family {
  def ofBoysAndGirls(numBoys: Int, numGirls: Int): Family = Family(numBoys + numGirls)
}

Another way to do that is to extract common features into a trait and extend it in both classes - that way you won't need to initialize parameters.

trait Family {
  def numPeople: Int
}
case class Family(numPeople: Int) extends Family
case class ComplexFamily(numBoys: Int, numGirls: Int) extends Family {
  val numPeople = numBoys + numGirls
}

Upvotes: 6

Related Questions