I recently found myself writing a lot of case class definitions like this
case class A(x: Int, a: A)
case class B(x: Int, b: B)
case class C(x: Int, c: C)
So they have common part and custom part. Right now, AFAIK, we don’t have the mechanism that would allow us to share parts of a case class. In a perfect world, I would be able to write
case class Base(x: Int)
case class A(a: A) extends2 Base
case class B(b: B) extends2 Base
case class C(c: C) extends2 Base
and then leverage all the benefits of case classes, so valid toString
, equals
, hashcode
and all the libs with special macro treatment for them.
Of course, extend
cannot be used for that purpose, but we could probably come up with a new keyword.
The tricky part is instantiation, where in this case we have a constructor with 1 visible parameter but we need to provide 2. One solution would be the desugaring that will provide an artificial constructor which would be the concatenation of all the extended case classes, so it looks like
val x = C(???, 1)
But this sounds a little bit complex and may be hard to understand and hard for tooling to support.
This also reminds trait parameters a bit, but the drawback of those is that you have to repeat all the parameters in the final class constructor so you can pass them down (if I remember and understand them correctly).
Second thing is that I’m not sure if macros (like one for deriving json codecs) would be able to work with trait parameters, and this is one of the most important parts.
WDYT?