为 class 层次结构定义通用副本,其中包含许多案例 classes

Define common copy for a class hierarchy with many case classes

我想定义一个 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 定义自动复制。有什么方法可以实现 "clone" doCopy 以便使用那些 case classes?

的自动 copy

I would like to define a class hierarchy with about 100 case classes deriving from common base.

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

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

我现在无法测试,所以这可能不会编译,但你可以自己想出大致的思路!

编辑:

为什么有 100 个子classes 是邪恶的:假设你在基础 class 中进行了一次更改,例如将其名称从 Base 更改为 BaseCloning - > 你必须在每个 child class 中更改它(100 个更改)。

如何避免这种情况取决于您要对 classes 做什么,检查 creationnalstructural patterns: factory, builder, prototype, flyweight, composite...总是想"how much work will I have if I change something in the base class? Will it affect all children?"

我发现在每个 case class 中定义 doCopy 实际上比定义每个 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() 的静态类型相同,即 CaseA,而不是 Base。为每个 case class 添加显式类型可能会更明显,但与仅将同一行复制粘贴到每个中相比,这需要更多的工作。这并不重要——当我通过 case class 类型进行复制时,我也可以使用 copy()。只有当我有 Base 时,我才需要 doCopy,因此将其声明为 def doCopy: Base = copy() 不会有什么坏处。