2

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

我定义了一个抽象的 No,接下来是一个字段,它的类型是 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")
}

但是,我发现我需要稍后在SpecificNode中更改该字段,所以我制作

case class SpecificNode(nxt: Node) extends Node {
  var next = nxt
}

但是,我不能分配给next某个特定节点的实例的字段,例如sn.next = ...,因为编译器抱怨next_不是节点的成员。

然后我改为var在抽象类 Node 中使用该next字段。

但是当我新建一个 NullNode 时,会抛出异常(因为我是这么定义的..)

那么我应该如何在这里使用var, def,val呢?我应该如何定义 NullNode,它表示不再有节点?

4

1 回答 1

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 库中实现的

于 2012-11-05T06:25:33.890 回答