Extending scala case class without constantly duplicating constructors vals?
Solution 1
As the previous commenter mentioned: case class extension should be avoided but you could convert your Edge class into a trait.
If you want to avoid the private statements you can also mark the variables as override
trait Edge{
def a:Strl
def b:Strl
}
case class EdgeQA(override val a:Strl, override val b:Strl, right:Int, asked:Int ) extends Edge
Don't forget to prefer def
over val
in traits
Solution 2
This solution offers some advantages over the previous solutions:
trait BaseEdge {
def a: Strl
def b: Strl
}
case class Edge(a:Strl, b:Strl) extends BaseEdge
case class EdgeQA(a:Strl, b:Strl, right:Int, asked:Int ) extends BaseEdge
In this way:
- you don't have redundant
val
s, and - you have 2 case classes.
Solution 3
Case classes can't be extended via subclassing. Or rather, the sub-class of a case class cannot be a case class itself.
Solution 4
Starting in Scala 3
, traits can have parameters:
trait Edge(a: Strl, b: Strl)
case class EdgeQA(a: Strl, b: Strl, c: Int, d: Int) extends Edge(a, b)
![LaloInDublin](https://i.stack.imgur.com/Jz3ax.jpg?s=256&g=1)
Comments
-
LaloInDublin about 3 years
Is there a way to extend a case class without constantly picking up new vals along the way?
For example this doesn't work:
case class Edge(a: Strl, b: Strl) case class EdgeQA(a: Strl, b: Strl, right: Int, asked: Int) extends Edge(a, b)
"a" conflicts with "a"
, so I'm forced to rename toa1
. But I don't want all kinds of extra public copies of "a" so I made it private.case class Edge(a: Strl, b: Strl) case class EdgeQA(private val a1: Strl, private val b1: Strl, right: Int, asked: Int) extends Edge(a, b)
This just doesn't seem clean to me... Am I missing something?
-
WestCoastProjects over 10 yearsWe lose the advantage of the Edge as a standalone class: before it could be instantiated and it had the object Factory methods
-
Jeffrey Aguilera over 10 yearsSo why are there
final case class
es? Thefinal
LocalModifier is what prevents the extension of acase class
, not some other language prohibition. See §5.2, p.63 of the Scala Reference -
jhegedus over 10 yearsFinal prevents extending a case class with anything ( i.e. case and not case classes), in addition to the built-in restriction to extend case classes with case classes.
-
Sohaib about 9 yearsbut I still need to redeclare a and b. What if the trait had some default value for a and be and I wish to use those values themselves.
-
Wolfsblvt almost 9 yearsCan you explain why def is preferred in traits?
-
BAR almost 9 yearsPlease do explain your last statement. Is it because the implementation can be either a function or a variable?
-
Kevin Meredith over 7 years
"case class extension should be avoided
". Can you please explain why, @bajohns? -
salvob over 6 yearsthis is definitely better
-
Bill'o over 6 yearsthis is an explanation on why to use def vs val
-
6infinity8 about 6 yearsGood but not perfect, we can't perfom sanity check on the variables this way without duplicating the code. Fortunately, Scala 3 will allow trait values as shown in this example.