【问题标题】:Case to case inheritance in ScalaScala中的案例继承
【发布时间】:2015-02-26 14:43:33
【问题描述】:

我有一个抽象类,我扩展并制作了许多案例类。现在我想复制那些只更改第一个参数的案例类的实例,所以我使用案例类的copy 方法。

由于我必须对从通用抽象类扩展而来的所有案例类执行此操作,而不是对所有案例类都执行此操作,因此我尝试使其具有通用性并将抽象类设为案例类。

然后 Scala 给了我这个:

case 类 Octopus 有 case 祖先 Organism,但禁止 case-to-case 继承。要克服此限制,请使用提取器在非叶节点上进行模式匹配。

代码:

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)

这就是我想做的。但是如果我不能使clone 方法工作,那么我将不得不为OctopusFrog 进行复制。

有什么建议可以减少这种冗长吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    一般情况下,您不能对案例类的 copy 方法进行抽象。我建议使用 Shapeless 或 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)
    

    【讨论】:

      【解决方案2】:

      仅使用标准 scala 在抽象(超)类上没有这样的通用复制方法:它如何知道如何克隆/复制所有子类?特别是将来可能会添加新的子类。

      据我所知,实现这种抽象方法的两种主要方法是:

      1) 在所有子类上创建一个匹配大小写的函数:

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

      那么每次添加新的子类,都需要在这个函数中添加。这最适合与sealed abstract class 一起使用。

      2) 将makeClone 方法添加到抽象API(名称clone 被保留):

      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)
      }
      

      请注意,虽然 (1) 中的函数始终返回 Organism,但这里的方法 Octopus.makeClone 返回 Octopus

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-02
        • 1970-01-01
        • 1970-01-01
        • 2021-02-14
        • 2019-09-26
        • 1970-01-01
        相关资源
        最近更新 更多