假设我有一棵普通的树:
sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T])
extends Tree[T] {
override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
override def toString = "."
}
大量代码已经依赖于该树并在模式匹配中使用Node
。
然后我决定我需要一个位置节点,只需一个单独的功能:
case class PositionedNode[+T](val value: T, val left: Tree[T], val right: Tree[T], x: Int, y: Int)
extends Tree[T] {
override def toString = s"T[$x, $y]($value $left $right)"
}
我希望基于PositionedNode
的新生成的树能够使用我的新代码和旧代码。我不想更改旧代码或原始定义,因为它太过分了。
我的第一个目的是从Node
继承它,但由于案例到案例的继承限制,我不能这样做。如果我从Tree
继承它,它将无法使用我的旧代码
我试图在SO上搜索这个,但我找不到满足这个问题的答案。解决这个问题的首选方法是什么?
答案 0 :(得分:4)
我遇到此问题的典型方法是将目标case class
重构为trait
,在重命名原始case class
时模仿旧行为:
sealed abstract class Tree[+T]
sealed abstract class Node[+T] extends Tree[T] {
def value: T
def left: Tree[T]
def right: Tree[T]
}
//renamed from Node
case class SimpleNode[+T](value: T, left: Tree[T], right: Tree[T])
extends Node[T] {
override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
override def toString = "."
}
case class PositionedNode[+T](val value: T, val left: Tree[T], val right: Tree[T], x: Int, y: Int)
extends Node[T] {
override def toString = s"T[$x, $y]($value $left $right)"
}
object Node {
def apply[T](value: T, left: Tree[T], right: Tree[T]) = SimpleNode(value, left, right)
def unapply[T](node: Tree[T]): Option[(T, Tree[T], Tree[T])] = node match {
case SimpleNode(v, l, r) ⇒ Some((v, l, r))
case PositionedNode(v, l, r, _, _) ⇒ Some((v, l, r))
case _ ⇒ None
}
}
像copy
这样的方法需要在这里进行额外的处理,当它们被广泛使用时,没有通用的解决方案