2012-05-02 6 views
1

세 가지 방법이 있습니다를 사용하여 공분산을 구현 :가상 유형 (추상 유형) 공분산을 보장하기 위해

  1. 순수 공분산 :
  2. 이 F-경계를 사용하여 캐스트를 사용하여 오버로드 :
  3. 공분산을 시뮬레이션하여 에펠 언어, ploymorphism 또는 가상 유형

그래서 가상 유형을 사용하여 솔루션을 테스트하고 있습니다. 다음 예제에서는 초록 유형을 사용합니다.

,
  • 우리는 3 개 추상 클래스 정의 그래프, 노드, 가장자리를
  • 그래프 클래스는이 방법을 정의 attachNode (노드)와 detachNode (노드)
  • 는 노드 클래스는이 방법을 정의 attachToGraph (그래프) 및 detachFromGraph()

우리가 서로 다른 도메인에 대해 서로 다른 서브 클래스를 생성합니다 inheretence 사용 : 네트워크 용

  • : class Network extends Graphclass Host extends Node ..
  • 화학상
  • : class Molecule extends Graphclass Atom extends Node ..
  • 유일한 제약은 예를 들어 원자에 부착하여 "키메라"을 만들지 않도록한다
  • ...

회로망. 그래서이 모델은 비교적 간단하다 :

abstract class Graph { 
    type CompatibleNode <: Node 
    protected var myNodes = new ArrayBuffer[CompatibleNode]() 

    def attachNode(node : compatibleNode) = { 
     .... 

     // Inform the node about the attachement so it can do update 
     node.attachToGraph(this) 

     // save the node 
     myNodes += node 
    } 
} 

abstract class Node { 
    type CompatibleGraph >: scala.Null <: Graph 
    protected var myGraph : CompatibleGraph = null 

    def attachToGraph(graph : compatibleGraph) = { 
     .... 

     // Inform the graph about the attachement so it can do update 
     graph.attachNode(this) 

     // save the node 
     myGraph = graph 
    } 
} 

그리고 우리가 가상 종류의 오버라이드 (override) 할 필요가 특별한 그래프 만드는 후

:

class Network extends Graph { override type CompatibleNode = Host} 
class Host extends Node { override type CompatibleGraph = Network} 

class Molecule extends Graph { override type CompatibleNode = Atom} 
class Atom extends Node { override type CompatibleGraph = Molecule} 

이 잘 (가 NIT 언어로 작동) 작업을해야을하지만 다른했다 오류 : graph.attachNode(this)를 호출

  • 첫째, 유형 불일치이 발견, graph.CompatibleNode를 requiered : Graph을, 그래서 나는이 캐스팅 :

    graph.attachNode (this.asInstanceOf [graph.CompatibleNode])를 NIT 언어가 할 것을

참고 암시 적 캐스트.

  • 둘째, detachFromGraph에 대한 그() 메소드 후 :

    클래스 노드 {

    ... 
    
    def detachFromGraph() = { 
    
        .... 
    
        // inform my graph 
        myGraph.detachNode(this.asInstanceOf[myGraph.CompatibleNode]) 
    
        ... 
    } 
    

    }

내가 오류 가지고 : myGraph.compatibleNode : requiered stable identifier를, 및 검색 후 읽기 사양 내가 찾은 : -> 안정적인 식별자 경로입니다 w en d는 식별자가 ->p.x이고 경로가 p이고 경로가 x이면 안정 멤버 -> 안정 멤버가 ..... 또는 비 휘발성 유형의 값 정의 -> 유형 매개 변수 .... 또는 추상 형식, ....

그래서 요약하면 경로에 추상 형식의 개체를 사용할 수 없습니까? 나는 모른다!

그래서 제안 사항이 있거나 심지어 가상 유형으로 스칼라 추상 유형을 사용할 수있는 경우에도 마찬가지입니다.

def detachFromGraph() { 
     detachFromThisGraph (myGraph) 
    } 

    def detachFromThisGraph (graph : CompatibleGraph) { 
     graph.detachNode(this.asInstanceOf[graph.CompatibleNode]) 
    } 

나는 안정적인 식별자가 조금 생각, 또는 왜 여기에 필요하지 않은 것을 :

+0

나는 에펠는 공분산을 "보장"표시되지 않습니다. 공분산을 다루는 그 방법은 심지어 반공 위치에있을지라도 공변 유형 매개 변수를 허용함으로써 Liskov 대체 원칙을 위반합니다. –

+0

나는 [이 질문] (http://stackoverflow.com/questions/5129943/tightly-coupled-parallel-class-hierarchies-in-c) (나는 비슷한 문제가있다)의 주석을 읽을 수있다. C++에서 이러한 아이디어 중 일부를 구현할 수 있습니다. 아무도 어떻게 알 수 있습니까? –

+0

당신은 어떤 종류의 공분산을 말하고 있습니까? 어쩌면 당신이 당신의 정의를 말할 수 있다면 도움이 될 것입니다. 'attachNode'를 호출하면'this'가'Node' (그리고'attachToGraph'에 대해 vv)와 호환 될 수 없으므로 정의가 불투명합니다. 왜냐하면 당신의 타입 스키마가 호환성 관계를 요구하거나 표현하지 않기 때문입니다 대칭입니다. – gzm0

답변

0

여기 а 해결 방법입니다.

1

이것은 작동하며 무한 루프도 제거합니다. 이 패키지는 패키지 전용 메소드를 설명 할 수 있습니다. 이제

package foo { 
    abstract class Graph { 
    type CompatibleNode <: Node 
    protected var myNodes = new ArrayBuffer[CompatibleNode]() 

    def attachNode(node: CompatibleNode) 
        (implicit ev: this.type <:< node.CompatibleGraph) { 

     // Inform the node about the attachement so it can do update 
     node.backAttach(ev(this)) 

     // save the node 
     myNodes += node 
    } 

    private[foo] def backAttach(node: CompatibleNode) { myNodes += node } 
    } 

    abstract class Node { 
    type CompatibleGraph >: scala.Null <: Graph 
    protected var myGraph: CompatibleGraph = null 

    def attachToGraph(graph: CompatibleGraph) 
        (implicit ev: this.type <:< graph.CompatibleNode) { 

     // Inform the graph about the attachement so it can do update 
     graph.backAttach(ev(this)) 

     // save the node 
     myGraph = graph 
    } 

    private[foo] def backAttach(graph: CompatibleGraph) { myGraph = graph } 
    } 
} 

:

class Network extends foo.Graph { override type CompatibleNode = Host} 
class Host extends foo.Node { override type CompatibleGraph = Network} 

class Molecule extends foo.Graph { override type CompatibleNode = Atom} 
class Atom extends foo.Node { override type CompatibleGraph = Molecule} 

을 그리고 그것을 밖으로 시도 :

object GraphTest { 
    val n = new Network() 
    val h = new Host() 

    n.attachNode(h) 

    val a = new Atom() 

    n.attachNode(a) // fails: type mismatch; 
    // found : Atom required: GraphTest.n.CompatibleNode (which expands to) Host 
}