案例继承

时间:2015-11-18 12:21:56

标签: scala

假设我有一棵普通的树:

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上搜索这个,但我找不到满足这个问题的答案。解决这个问题的首选方法是什么?

1 个答案:

答案 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这样的方法需要在这里进行额外的处理,当它们被广泛使用时,没有通用的解决方案