我正在尝试更改二叉树中的结束节点。如何制作方法change_right_tree和change_left_tree?
编译器抱怨我正在重新分配给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}
}
答案 0 :(得分:1)
解决方案:如果您删除' +'从Node类声明中,您的代码将被编译。
说明:
当您使用协变类型[+ T]声明类时,您可以声明具有较窄类型的子类。因此,必须使用协变类型声明Tree类以允许声明case对象End。
但是当你希望它是可变的时,声明具有协变类型[+ T]的类Node是不正确的。为了理解它,最好想象一下编译器没有阻止你并允许你编译下面的代码(为了简单起见,我删除了其他方法):
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)
现在Node [Int]是Node [String]的左侧节点。所以混合协方差和可变性会打破类型安全。
答案 1 :(得分:0)
def change_left_tree( new_tree : Tree[T]): Tree = { new Tree (this.question, new_tree, this.right)
}