0

I am trying to inherit a class in Scala. My Parent class is

case class Person (name:String, age:Int, valid:Boolean)

My child class is

case class MarriedPerson (override val name: String,
  override val age: Int,
  override val valid: Boolean,
  spouse: Person) extends Person(name, age, valid)

When I try this, I get an error saying

:13: error: case class MarriedPerson has case ancestor Person, but case-to-case inheritance is prohibited. To overcome this limitation, use extractors to pattern match on non-leaf nodes.

  1. Why is this the case and how I get around this to get a case class to inherit another case class?
  2. If I remove the "case" in the parent class, I get an error saying that

    :15: error: value name overrides nothing override val name: String,

Why can't a case class not inherit from a normal class in this case?

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
Srinivas
  • 2,010
  • 7
  • 26
  • 51

1 Answers1

2

You cannot inherit from one case class to another. In theory its possible to inherit from a case class to a non-case class, but that's not recommended (which is why it's a good practice to make your case classes final - more on the topic in this post).

Case classes have, among other peculiarities, that of exposing publicly all of the constructor arguments. This does not happen for normal classes, which is why to make your snippet of code work you should just prepend all of Person's arguments with val.

Thus, the following is valid syntax:

class Person(val name: String, val age: Int, val valid: Boolean)

case class MarriedPerson(
  override val name: String,
  override val age: Int,
  override val valid: Boolean,
  spouse: Person) extends Person(name, age, valid)

However, for your information, it is also quite common to use traits for this kind of situations, which allows for greater flexibility (traits support multiple inheritance) and a slightly less verbose syntax, as follows:

trait Person {
  def name: String
  def age: Int
  def valid: Boolean
}

case class MarriedPerson(
  name: String,
  age: Int,
  valid: Boolean,
  spouse: Person) extends Person

If you are curious on why it's possible to define defs in traits that are overridden by vals in sub-classes, it's because Scala implements the Uniform Access Principle.

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
  • Thank you very much for your explanation, but if that is the case (one case class cannot inherit another case class) we cannot do pattern matching on nested case class. Is that correct? – Srinivas Jul 17 '17 at 07:08
  • You cannot inherit, but you can compose, meaning that you can do pattern matching on nested case classes. However, if you mean something like your case, where nested case classes are also somehow recursive, this limitation would not make it possible to make it work out of the box. Pattern matching can however be enhanced by providing an `unapply` function. Here is an example that you can run in your Scala console to show you how this would work: https://gist.github.com/stefanobaghino/fb7c1a4071cc741fcb84af4ed2dc060c – stefanobaghino Jul 17 '17 at 07:22
  • If you want to know more about extractors and how to extend pattern matching you can read this excellent post: http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html – stefanobaghino Jul 17 '17 at 07:22