Case to case inheritance in Scala

前端 未结 2 875
Happy的楠姐
Happy的楠姐 2020-12-14 20:59

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

相关标签:
2条回答
  • 2020-12-14 21:26

    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)
    
    0 讨论(0)
  • 2020-12-14 21:42

    Using only standard scala there is no such generic copy method on abstract (super) class: how would it know how all subclasses can be cloned/copied? Especially that new subclasses could be added in the future.

    To my knowledge, the two main approaches to implement such abstract method are:

    1) make a function that match-case on all subclasses:

    def clone(o: Organism) = o match {
      case o: Octopus => o.copy(legs = -1) 
      case f: Frog    => f.copy(legs = -1) 
    }
    

    Then each time a new subclass is added, it needs to be added in this functions. This is most appropriate for use with sealed abstract class.

    2) add a makeClone method to the abstract API (the name clone being reserved):

    abstract class Organism(legs: Int){
      def makeClone(legNumber: Int): Organism
    }
    case class Octopus(legs: Int, weight: Double) extends Organism(legs) {
      def makeClone(legNumber: Int) = this.copy(legs = legNumber)
    }
    

    Note that while the function in (1) always returns an Organism, here the method Octopus.makeClone returns an Octopus.

    0 讨论(0)
提交回复
热议问题