2014-11-27 3 views
1

Я пытаюсь изменить свои конечные узлы в своем двоичном дереве. Как создать методы change_right_tree и change_left_tree?scala бинарное дерево, добавление элемента

Компилятор жалуется, что я переназначаю значение val. Но когда я меняю вещи на var, я получаю ковариантные ошибки.

sealed abstract class Tree[+T] { 
} 
case object End extends Tree[Nothing] { 
    override def toString = "." 
} 

case class Node[+T](var question: String, left: Tree[T] = End, right: Tree[T] = End) extends Tree[T] { 
    override def toString = "T(" + question.toString + " " + left.toString + " " + right.toString + ")" 

    def set_question(str : String) = {question = str} 

    def get_answer(answer : Boolean) = { 
    if (answer){ 
     left 
    }else { 
     right 
    } 
    } 
    // unclear on what I need to do to make this work 
    def change_left_tree(new_tree : Tree[T]) = {this.left = new_tree} 
    def change_right_tree(new_tree : Tree[T]) = {this.right = new_tree} 
} 
+1

вы привязывания изменить листья? Или вы пытаетесь изменить только первый левый узел с 1-го узла? – McShep

+0

im, пытающийся «заменить» текущий левый узел новым узлом, который я создал. Кажется, я пытаюсь изменить лист? (не совсем уверен в терминологии, но если раньше «осталось» значение 4 и продолжалось вниз по дереву, я хочу изменить «левый» на 10 и сделать его последующие ветви «END», «END») – user1639926

ответ

1

Решение: Если вы удалите «+» из декларации класса узла, код будет скомпилирован.

Объяснение:

Когда вы объявляете класс с ковариантным типом [+ T], то вы можете объявить подклассы с более узким типом. Поэтому класс Tree должен быть объявлен с ковариантным типом, чтобы разрешить объявление объекта объекта End.

Но объявление класса Узел с ковариантным типом [+ T] был неправильным, если вы хотите, чтобы он изменялся. Для того, чтобы лучше понять его себе на минуту, что компилятор не остановить вас и позволил вам скомпилировать следующий код (я удалил другие методы для простоты примера):

case class Node[+T](var question: String, var left: Tree[T] = End, var right: Tree[T] = End) extends Tree[T] { 
    def change_left_tree(new_tree : Tree[T]) = {this.left = new_tree} 
    def change_right_tree(new_tree : Tree[T]) = {this.right = new_tree} 
} 

Теперь вы можете сделать следующее:

val stringNode:Node[String] = new Node("string node") 
val intNode:Node[Int] = new Node("int node") 
val anyNode:Node[Any] = stringNode 
anyNode.change_left_tree(intNode) 

И теперь узел [Int] - это левый узел узла [String]. Таким образом, смешивание ковариации и изменчивости приведет к нарушению безопасности типов.

+0

Но + T должен разрешить мой End Node, который является Tree [Nothing], как я могу изменить это, чтобы заставить его работать? Или сделать так, чтобы я мог создавать конечные узлы? – user1639926

0
  1. В определении узла, левое и правое свойства уже определены как End.
  2. В методах change_left_tree и change_right_tree вы изменяете значение слева и справа вместо того, чтобы возвращать новое дерево.
def change_left_tree(new_tree : Tree[T]): Tree = { 
    new Tree (this.question, new_tree, this.right) 

}

+0

да. это поведение, которое я хочу. Я думаю. – user1639926

+0

изменен мой пост с некоторым кодом (который, я думаю, синтаксис справа). –

Смежные вопросы