2010-05-09 3 views
3

У меня есть нормальное дерево, определенное в Scala.Расширение существующей структуры данных в Scala

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

Теперь я хочу добавить переменную-член ко всем узлам и листьям в дереве. Возможно ли это с помощью ключевого слова extend или мне нужно изменить древовидные классы, добавив [T]?

Update:
Кажется, что мой вопрос был неправильно понят. Пример должен очистить его:

Мне нужна эта структура дерева (на самом деле что-то более сложная) имеет два двойника в одном контексте. В другом контексте мне нужно, чтобы у него была одна строка. И все же в другом контексте мне нужно чистое дерево без каких-либо (дополнительных) членов. И я хотел бы сначала два варианта: be третий вариант. псевдокод:

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) { ... } 

Я хочу е, чтобы иметь возможность обрабатывать все деревья.

ответ

0

Вы не должны изменить класс дерева, так как вы всегда можете создать промежуточный подкласс между деревом и узлом/Leaf:

 

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

Однако, вы не можете достичь этого путем смешивания признака к узлу и листу, если вы хотите, чтобы дополнительный член передавался как параметр.

0

Абстрактные классы могут иметь конструкторы (черты не могут), так что вы можете просто поставить общие элементы в abstract class Tree:

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

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

и так далее. Обратите внимание, что вам необходимо предоставить параметры конструктора базового класса в предложении extends определения подкласса.

+0

Вы изменили класс дерева. Я хочу избежать этого, поскольку он используется во многих местах, и мне нужно больше богатого дерева только в одном месте. –

+2

@ Łukasz Lew: Затем введите новый слой в структуре наследования, который служит для захвата этого различия и поместите общие элементы в один из (абстрактных) классов на этом уровне. –

0

Если добавляемые вами члены (и) действительны для всех объектов (и подклассов), то логическим местом является их размещение в самом дереве.

У вас есть две техники, доступные вам двумя. Как уже отмечалось другими, вы можете сделать эти конструктор Params на абстрактном классе:

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

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

Вы можете также сделать их регулярными Vals/вары и специализируется на подклассы. Это, возможно, лучшее решение, так как это делает его легче вычислить эти свойства, вместо того, чтобы просто ромашка-цепочку их с помощью конструкторов:

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 
} 

Использования ленивых Va здесь легче рассуждать о порядке инициализации вашего объекта, его также избегает любых вычислительных издержек, если свойство никогда не используется. Это также хорошо показывает, как методы 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 
} 

Это добавляет уровень косвенности. Но я чувствую, что вы концептуализируете что-то на одном шаге, где два необходимы.