我想实现某种简单的链接列表。
我定义了一个摘要否,接下来是一个字段,其类型为节点。然后,我有一堆其他特定节点,继承了抽象节点。
我这样写:
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")
}
但是,我发现我需要在稍后在特定节点中更改字段,所以我做
case class SpecificNode(nxt: Node) extends Node {
var next = nxt
}
但是,我无法分配到某些特定节点的实例的next
字段,例如sn.next = ...
,因为编译器抱怨next_
不是Node的成员。
然后,我更改为在next
字段的抽象类节点中使用var
。
但是,当我新的一个nullnode时,将会抛出异常(因为我定义了SO ..)
那么,我应该在这里如何使用var
,def
,val
?我应该如何定义nullnode,它可以表示不再表示节点?
您需要在接口中明确定义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库中实现的不变列表