2013-02-15 5 views
2

This Scala tutorial은 저를 혼동시킵니다. Node 추상 형식은 ... 다형성의 전통적인 규칙에 따라하지 않는 것스칼라 추상 유형 및 다형성

type Node <: NodeIntf    // NodeIntf is assignable to Node. 
abstract class NodeIntf { 
    def connectWith(node: Node): Edge 
} 
class NodeImpl extends NodeIntf { 
    def connectWith(node: Node): Edge = { 
    val edge = newEdge(this, node) // NodeImpl (this) is assignable to NodeIntf. 
    edges = edge :: edges 
    edge 
    } 
} 
protected def newEdge(from: Node, to: Node): Edge 

Node = NodeIntfNodeIntf = NodeImpl 경우에, 우리는 왜 Node = NodeImpl을 할 수 있습니까? 나는 분명히 위의 코드가 컴파일되지 않을 것이기 때문에 - 왜 '자체 형식의 참조'를 사용해야합니까? (see tutorial)

답변

7

<:의 의미를 뒤집 았습니다. NodeNodeIntf에 할당, 즉이다 : 이제

val x: NodeIntf = y: Node 

, 당신은 사실이 아니다있는 Node = NodeIntfNodeIntf = NodeImpl 말을 더 아래. Node임의의 하위 유형 NodeIntf이고 NodeImplNodeIntf의 특정 하위 유형입니다. 의 측면에서

NodeNodeIntf이다하는이며, NodeImplNodeIntf입니다,하지만 그들 사이의 관계에 대한 의미가 없습니다 - 당신은뿐만 아니라 모두 NodeNodeImpl는 모두 하위 유형이 있다고 말했다 수 Any.

3

첫째, 여기에 일종의-입니다 코드의 최소한의, 독립적 인 버전 : 당신이 그것을 컴파일하려고하면

abstract class Graph { 
    type Node <: NodeIntf 

    case class Edge(s: Node, d: Node) 

    abstract class NodeIntf { 
    def connectWith(node: Node): Edge 
    } 

    class NodeImpl extends NodeIntf { 
    def connectWith(node: Node): Edge = { 
     val edge = newEdge(this, node) 
     edge 
    } 
    } 

    def newEdge(from: Node, to: Node): Edge = Edge(from, to) 
} 

, 당신은

found : NodeImpl.this.type (with underlying type Graph.this.NodeImpl) 
required: Graph.this.Node 
    val edge = newEdge(this, node) 
        ^

이유에를 얻을 수 있습니다 오류 메시지는 Node추상 유형입니다. 상한선은 NodeIntf이지만 그럼에도 불구하고 여전히 추상적입니다. 즉, 요약 Graph의 구현은 Node에서 까지 하위 유형 NodeIntf을 자유롭게 설정하거나 바인딩 할 수 있습니다.

NodeImpl의 인스턴스를 newEdge으로 전달하려고 시도하면 Node이 필요합니다. NodeImplNodeIntf의 하위 유형이지만 Graph의 구현은 의 하위 유형을 NodeImpl으로 바인딩하여 Node을 더 이상 제한하도록 결정할 수 있습니다. 이는 newEdge으로 전화하는 것을 불법으로 만듭니다. Graph 이후 구현은 더 이상 Node을 결합 할 수 없기 때문에

당신이 이미 NodeIntf의 유형 별칭하여, 예를 들면, Node 결합하면

,

type Node = NodeIntf 

는 위의 코드를 컴파일합니다.