我想实现某种简单的链表。
我定义了一个抽象的No,接下来是一个字段,它的类型是Node。 然后我有一堆其他特定的Node,继承了抽象节点。
我这样写:
abstract class Node {
def next: Node
}
case class SpecificNode(nxt: Node) extends Node {
val next = nxt
}
object NullNode extends Node{
val next = new Exception("no more node")
}
但是,我发现我需要稍后在SpecialNode中更改字段, 所以我做了
case class SpecificNode(nxt: Node) extends Node {
var next = nxt
}
但是,我无法分配某个特定节点的实例的next
字段,例如sn.next = ...
,因为编译器抱怨next_
不是Node的成员。
然后我改为在var
字段的抽象类Node中使用next
。
但是当我新建一个NullNode时,会抛出异常(因为我已经定义了......)
那我该如何在这里使用var
,def
,val
?
我应该如何定义NullNode,即不再表示节点?
答案 0 :(得分:4)
您需要在界面中明确定义getter / setter。在我们的例子中(没有改变结构和想法):
trait Node {
def next: Node
def next_=(node: Node)
}
// `var next: Node` generates implementations for `def next: Node` and `def next_=(node: Node)`
case class SpecificNode(var next: Node) extends Node
object NullNode extends Node {
def next = throw new Exception("no more node")
def next_=(node: Node) { throw new Exception("can't change next on null node") }
}
val n1 = SpecificNode(NullNode)
val n2 = SpecificNode(SpecificNode(NullNode))
val n3: Node = SpecificNode(n1)
// some function to test our structure:
def length(n: Node, prev: Int = 0): Int = if (n == NullNode) prev else length(n.next, prev + 1)
println(length(n3))
n3.next = n2
println(length(n3))
旁注:这是可变链表,我建议你检查标准scala库中如何实现不可变列表