Case to case inheritance in Scala

scala

Solution

You can't abstract over case class' `copy` methods generically. I'd suggest using Lenses from Shapeless or Monocle:

trait Organism { def legs: Int }
// monocle @Lenses uses a macro to generate lenses
@Lenses case class Octopus(override val legs: Int, weight: Double, ...)
  extends Organism
@Lenses case class Frog(val legs: Int, ...) extends Organism

def clone[O <: Organism](o: O, legsLens: Lens[O, Int]): O =
  legsLens.set(-1)(o)

val myOctopus = Octopus(8, 2.4, ...)
val myFrog = Frog(2, ...)

// use the generated Lenses
val cloneOctopus: Octopus = clone(myOctopus, Octopus.legs)
clone(myFrog, Frog.legs)

Problem

I have an abstract class which I extend and make numerous case classes. Now I want to copy instances of those case classes just changing first parameter, so I use case class' `copy` method. Since I have to do this for all case classes that have been extended from common abstract class, rather than doing it for all, I tried to make it general and made the abstract class a case class. Then Scala gives me this: case class Octopus has case ancestor Organism, but case-to-case inheritance is prohibited. To overcome this limitation, use extractors to pattern match on non-leaf nodes. Code: ``` abstract class Organism(legs: Int) case class Octopus(override val legs: Int, weight: Double, ...) case class Frog(override val legs: Int, ...) def clone(o: Organism) = o.copy(legs = -1) ``` This is what I want to do. But if I can't make the `clone` method work, then I will have to do copying for both `Octopus` & `Frog`. Any suggestions, to decrease this verbosity?

Original source