Scala中的大小写继承

时间:2015-02-26 14:43:34

标签: scala

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

因为我必须对从公共抽象类扩展而来的所有案例类执行此操作,而不是对所有案例类执行此操作,所以我尝试使其成为通用的,并使抽象类成为案例类。

然后Scala给了我这个:

  

案例类八达通有案例祖先有机体,但禁止个案继承。要克服此限制,请使用提取器在非叶节点上进行模式匹配。

代码:

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方法有效,那么我将不得不复制Octopus& Frog

有任何建议,以减少这种冗长吗?

2 个答案:

答案 0 :(得分:10)

您无法一般性地抽象案例类“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)

答案 1 :(得分:0)

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.