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

时间:2012-11-05 05:56:50

标签: scala

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

我定义了一个抽象的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时,会抛出异常(因为我已经定义了......)

那我该如何在这里使用vardefval? 我应该如何定义NullNode,即不再表示节点?

1 个答案:

答案 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库中如何实现不可变列表