使用def/val/var以及如何在链接列表中定义空元素



我想实现某种简单的链接列表。

我定义了一个摘要否,接下来是一个字段,其类型为节点。然后,我有一堆其他特定节点,继承了抽象节点。

我这样写:

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 ..)

那么,我应该在这里如何使用vardefval?我应该如何定义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库中实现的不变列表

最新更新