2017-01-22 1 views
0

Ich habe bei der Verwendung von Merkmalen auf ein Problem gestoßen. Der folgende Code überschreibt newEdge mithilfe eines Merkmals.Warum gibt Edge keinen DirectedEdge zurück?

Die ersten beiden Behauptungen zeigen das Verhalten ohne das DirectedGraph-Merkmal. Das nächste Merkmal zeigt das erwartete Verhalten mit DirectedGraph, aber die Methode des Merkmals scheint in der letzten Anweisung nicht verwendet zu werden.

Die letzte Bestätigung schlägt fehl mit.

Ich fragte mich, wie ich dieses Verhalten beheben könnte, damit die letzte Behauptung passieren kann.

Antwort

0

Hier ist, was semantisch in def dgraph = new Graph() as DirectedGraph passiert:

class MyProxy implements DirectedGraph { 
    Graph myGraph 

    MyProxy(Graph graph) { 
     myGraph = graph 
    } 

    def invokeMethod(String name, Object args) { 
     myGraph.invokeMethod(name, args) 
    } 
} 

def dgraph = new MyProxy(new Graph()) 

Ein solches Objekt implementiert eine Eigenschaft und die Delegierten alle nicht definierten Anrufe ursprüngliche Objekt, das heißt Graph Instanz.

assert dgraph.newEdge() instanceof DirectedEdge funktioniert, weil newEdge Methode von der Eigenschaft abgeleitet ist.
assert dgraph.edge() instanceof DirectedEdge schlägt fehl, weil es keine edge Methode gibt, wird dieser Aufruf an die ursprüngliche Graph Instanz delegiert, die wiederum keine Kenntnisse über Proxy-Wrapper hat.

class Edge {} 

class DirectedEdge extends Edge {} 

class Graph { 
    def edge() { newEdge() } 
    def newEdge() { new Edge() } 
} 

class DirectedGraph extends Graph { 
    def newEdge() { new DirectedEdge() } 
} 

def graph = new Graph() 
assert graph.newEdge() instanceof Edge 
assert graph.edge() instanceof Edge 

def dgraph = new DirectedGraph() 
assert dgraph.newEdge() instanceof DirectedEdge 
assert dgraph.edge() instanceof DirectedEdge 
+0

Danke für die Hilfe:

Dies kann mit reiner Klassenvererbung implementiert werden! Dies füllt tatsächlich viele Lücken in meinem Wissen. Ich werde wahrscheinlich mit so etwas wie diese graph.metaClass.newEdge = gehen {-.> return Graph & NewEdge() withTraits (DirectedEdge) .} Dies ist die Komplexität helfen zu vermeiden, wenn Gewicht und Attribute hinzugefügt werden. –

+0

@JohnMercier Gern geschehen! Ich empfehle, nicht mit Metaklassenmagie zu gehen, bitte bedenke Vererbung. Sie können mehr Details darüber angeben, was Sie erreichen möchten, damit ich Ihnen mit einer anderen Lösung helfen kann. – Dany

+0

Ich bin mir nicht sicher, ob die Vererbung funktioniert. Dies ist das Projekt https://github.com/moaxcp/graph-dsl. Mein Ziel ist es, ein Skript mit einem Graphen als Delegierten zu erstellen. Ich möchte es leicht machen, einen Graphen mithilfe einer Apply-Methode in einen gerichteten Graphen zu verwandeln. –

Verwandte Themen