noncom
noncom

Reputation: 4992

Scala child case class param name conflict with parent case class param name

Let us assume we have the two following classes:

abstract case class MyParent(param: Int) {
   // ...
}

case class MyChild(param: Int) extends MyParent(param: Int) {
   // ...          ^^^^^                        ^^^^^
}

Making them both case classes resulted in an error in both param usage places, which says that it needs the override modifier that will override the value from the parent class. This looks strange to me.. why do I have to invent other param names here.. why is this order of things enforced? Where is the profit?

Upvotes: 1

Views: 880

Answers (4)

Dan Burton
Dan Burton

Reputation: 53705

As far as my limited Scala knowledge goes, case classes are typically used for immutable algebraic data types and pattern matching. Therefore, instead of creating a "child class", you should probably instead create a class which contains the "parent" class.

> case class MyParent(param: Int)
defined class MyParent

> case class MyChild(param: Int, parent: MyParent)
defined class MyChild

> def foo(c: MyChild) = c match {
    case MyChild(p, MyParent(p2)) => println("p: " + p + ", p2 " + p2)
  }
foo: (c: MyChild)Unit

> foo(MyChild(3, MyParent(4)))
p: 3, p2 4

Upvotes: 1

Alexey Romanov
Alexey Romanov

Reputation: 170815

Where is the profit?

Simply the lack of a not-too-useful special case. param in case class MyChild(param: Int) is a class member as well as a constructor parameter, so one of ancestors already has a (non-abstract) param member, it has to be overridden. And Scala requires override keyword when overriding everywhere else, so it requires it here as well.

Upvotes: 1

Heiko Seeberger
Heiko Seeberger

Reputation: 3722

You never should derive a case class from another case class!

Try this in a REPL started with scala -deprecation:

scala> case class Foo(foo: String)
defined class Foo

scala> case class Bar(override val foo: String) extends Foo(foo)
<console>:9: warning: case class `class Bar' has case ancestor `class Foo'.  Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed.  You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.

Upvotes: 7

Andy Petrella
Andy Petrella

Reputation: 4345

A quick fix for that is to do this

abstract case class MyParent(param: Int) {
   println("Form parent : " + param)
}

case class MyChild(override val param: Int) extends MyParent(param) {
   println("Form child : " + param)
}

val c = MyChild(10);

This will result in this

>> From parent : 10 
>> From child : 10 

Actually the extends MyParent() is not like in Java. This is a way to tell MyChild extends MyParent, and call the super constructor of the latter at first.

Upvotes: 1

Related Questions