2012-11-05 1 views
2

간단한 연결 목록을 구현하려고합니다.def/val/var 사용 및 링크 된 목록의 null 요소 정의 방법

다음 필드가있는 추상 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_이 Node의 멤버가 아니기 때문에 불만을 토로합니다.

그런 다음 next 필드의 추상 클래스 노드에서 var을 사용하도록 변경되었습니다.

하지만이 NullNode 새로운 때 (내가 그렇게 정의하기 때문에 ..), 예외가 던져 질 것이다

그래서 여기 var, def, val를 사용하는 방법? 더 이상 노드를 나타내지 않는 NullNode를 어떻게 정의해야합니까?

답변

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

사이드 참고 :이 변경 가능한 연결 목록, 난 당신이 표준 스칼라 라이브러리

+0

감사합니다 세르게이에서 구현하는 방법을 불변의리스트를 확인하는 것이 좋습니다입니다! 나는 setter를하려고했지만,'next_ ='어떤 공간이 아니라'next_ ='를 알아 차리지도 못했다. 그래, 이건 변경할 수 있습니다, 난 그냥 스칼라를 사용하기 시작하고 빠른 프로토 타입을하고 싶지 표준 라이브러리에서 링크 된 불변의 구현은 내가 지금 알 필요가 없을 수도 있습니다 고급 기능을 포함 수 두려워했다 ...이 나쁘다. 나는 알고있다. 그러나 나는 그것을 만들려고 노력할 것이다. 고마워 fr 조언! – monica