为 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 做什么,检查 creationnal 和 structural 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()
不会有什么坏处。
我想定义一个 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 做什么,检查 creationnal 和 structural 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()
不会有什么坏处。