Reputation: 862
I am trying to change my end nodes in my binary tree. How do I make the methods change_right_tree and change_left_tree?
The compiler is complaining that I am reassigning to val. But when I change things to var, I get covariant errors.
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}
}
Upvotes: 1
Views: 646
Reputation: 3922
Solution: If you remove '+' from Node class declaration your code will compile.
Explanation:
When you declare class with covariant type [+T] then you can declare subclasses with narrower type. So Tree class has to be declared with covariant type to allow declaring case object End.
But declaring class Node with covariant type [+T] was incorrect when you wanted it to be mutable. To understand it better imagine for a moment that compiler didn't stop you and allowed you to compile following code (I removed other methods for simplicity of example):
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}
}
Now you can do the following:
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)
And now Node[Int] is left node of Node[String]. So mixing covariance and mutability would break type safety.
Upvotes: 1
Reputation: 955
def change_left_tree( new_tree : Tree[T]): Tree = { new Tree (this.question, new_tree, this.right)
}
Upvotes: 0