2010-05-09 49 views
3

我在Scala中定义了一个正常的树。在Scala中扩展现有的数据结构

sealed abstract class Tree 
object Tree { 
    case class Node (...) extends Tree 
    case class Leaf (...) extends Tree 
} 

现在我想添加一个成员变量到树中的所有节点和树叶。 扩展关键字可能吗?或者我必须通过添加[T]来修改树类吗?

更新:
看来我的问题被误解了。 示例应清除它:

我需要这个树结构(实际上更复杂的东西)在一个上下文中有两个双打。 在另一种情况下,我需要它有一个字符串。然而在另一种情况下,我需要没有任何(额外)成员的纯树。而我想第一个两个变种为的第三个变种。 伪代码:

DTree extends Tree with Touple2[Double, Double] 
object DTree { 
    case class Node (...) extends Tree.Node with Touple2[Double, Double] 
    case class Leaf (...) extends Tree.Leaf with Touple2[Double, Double] 
} 

STree extends Tree with String 
object DTree { 
    case class Node (...) extends Tree.Node with String 
    case class Leaf (...) extends Tree.Leaf with String 
} 

... 

def f (t : Tree) { ... } 

我想F到能够处理所有的树木。

回答

0

您不必修改树类,因为你总是可以创建树和节点/叶之间的中介子类:

 

abstract class ExtraMember[T](member:T) extends Tree 
 

但是,你不能在一个特点的混合实现这一目标如果您希望将额外成员作为参数传递给Node和Leaf。

0

抽象类可以有构造函数(特征可能不会),那么你可以把公共元素在abstract class Tree

abstract 
class Tree(te1: String, te2: Int) 

case 
class Node(...) 
extends Tree(te1Arg, te2Arg) 

等。请注意,您必须在子类定义的extends子句中提供基类构造函数参数。

+0

您修改了Tree类。我想避免这种情况,因为它在很多地方都有使用,我只需要在一个地方需要更丰富的树。 – 2010-05-09 17:40:27

+2

@ŁukaszLew:然后在继承结构中引入一个新层,用于捕获这种区别,并将共享元素放置在该级别的(抽象)类之一中。 – 2010-05-09 18:09:32

0

如果您要添加的成员对所有Tree对象(和子类)有效,那么合乎逻辑的地方就是将它们放入Tree对象本身。

你在这里有两种技术可用。正如其他人所提到的,你可以在抽象类使这些构造PARAMS:

sealed abstract class Tree(prop1: String, prop2: Int) 

case class Node(prop1: String, prop2: Int) extends Tree(prop1, prop2) 

你也可以让他们定期丘壑/ VAR和专门的子类。这无疑是一个更好的解决方案,因为它更容易,而不是计算的简单菊花链式他们通过构造这些属性:

sealed abstract class Tree { 
    def prop1 : String 
    def prop2 : Int 
} 

case class Node(a:String, b:Int) extends Tree { 
    lazy val prop1 = "[" + a + "]" 
    lazy val prop2 = b + 42 
} 

使用懒瓦尔斯在这里更容易推理的对象的初始化顺序,如果该属性从不使用,也可以避免任何计算开销。这也很好地显示了Scala中的方法如何通过属性实现,即所谓的统一访问原则。

如果采取这种方式,那么它也可以通过一个特点,介绍属性:

sealed abstract class Tree 

trait TreeExtras { 
    def prop1 : String 
    def prop2 : Int 
} 

case class Node(a:String, b:Int) extends Tree with TreeExtras { 
    lazy val prop1 = "[" + a + "]" 
    lazy val prop2 = b + 42 
} 

你也应该随时使用自助型等中的。

2

如果我正确理解你,你希望你的一些树节点有一个类型的字段。我认为你要找的是abstract type。它们就像泛型一样,但更适合分类。像这样的东西。

sealed abstract class Tree 

trait TypedTree { 
    type T 
    val value:T 
} 

然后,当我修改你的榜样,结果:

trait DTree extends TypedTree { 
    type T = Touple2[Double, Double] 
} 
object DTree { 
    case class Node (...) extends Tree.Node with DTree 
    case class Leaf (...) extends Tree.Leaf with DTree 
} 

trait STree extends TypedTree { 
    type T = String 
} 
object DTree { 
    case class Node (...) extends Tree.Node with STree 
    case class Leaf (...) extends Tree.Leaf with STree 
} 

这增加了间接的级别。但是我觉得你在一个步骤中需要两个概念化概念。