为具有许多案例类的类层次结构定义公共副本

时间:2017-12-12 17:38:48

标签: scala clone case-class

我想定义一个类层次结构,其中约有100 case classes派生自公共基础。这些类型描述了AST层次结构中的节点,如this one。我想做一些事情:

trait Base {
  def doCopy: Base
}

trait CloneSelf[T <: CloneSelf[T]] extends Base {
  self: T =>

  def copy(): T
  override def doCopy: T = copy()
}


case class CaseA(a: String) extends Base with CloneSelf[CaseA]

case class CaseB(b: Int) extends Base with CloneSelf[CaseB]

这会产生错误,因为copy的存在会阻止case classes定义自动副本。有没有办法如何实现&#34;克隆&#34; doCopy这样使用copy的自动case classes

2 个答案:

答案 0 :(得分:1)

  

我想定义一个类层次结构,其中包含大约100个从公共基础派生的案例类。

不要这样做,你绝对应该找到一个模式来避免它!如果你想这样做......试试ducktyping

trait CloneSelf[T <: {def copy(): T}] {
  self: T  =>
    override def doCopy: T = copy()
}

我现在无法测试,所以这可能不会编译,但你可以自己弄清楚这个概念!

编辑:

为什么有100个子类是邪恶的:想象你在基类中执行一个更改,例如将其名称从Base更改为BaseCloning - &gt;你必须在每个儿童班(100次改变)中改变它。

如何避免这种情况取决于您对类的操作,检查 creationnal 结构模式:factory,builder,prototype,flyweight,composite .. 。如果我改变基类中的某些东西,总是要考虑&#34;我将拥有多少工作?它会影响所有孩子吗?&#34;

答案 1 :(得分:0)

我发现在每个doCopy中定义case class实际上比定义从CloneSelf继承的每个类要少。代码如下所示:

trait Base {
  def doCopy: Base
}

case class CaseA(a: String) extends Base {
  def doCopy = copy()
}

case class CaseB(b: Int) extends Base {
  def doCopy = copy()
}

我很惊讶地发现,如果在重写方法上没有显式类型,则编译器会推断出类型,因此CaseA("a").doCopy的静态类型与CaseA("a").copy()的静态类型相同,即{{1} },而不是CaseA。为每个Base添加显式类型可能更为明显,但与仅将相同行复制粘贴到每个类中相比,这将需要更多工作。这并不重要 - 当我通过case class类型进行复制时,我也可以使用case class。只有当我需要copy() Base时才需要doCopy,因此声明它def doCopy: Base = copy()会造成很小的伤害。