2017-01-22 54 views
0

我在使用特質時遇到了一個問題。以下代碼使用特徵覆蓋newEdge。爲什麼不能返回DirectedEdge?

#!/usr/bin/env groovy 
class Edge {} 
trait DirectedEdge {} 
class Graph { 
    def edge() { 
     newEdge() 
    } 
    def newEdge() { 
     return new Edge() 
    } 
} 
trait DirectedGraph { 
    def newEdge() { 
     return new Edge().withTraits(DirectedEdge) 
    } 
} 

def graph = new Graph() 
assert graph.newEdge() instanceof Edge : 'newEdge returns Edge' 
assert graph.edge() instanceof Edge : 'edge returns an Edge' 

def dgraph = new Graph() as DirectedGraph 
assert dgraph.newEdge() instanceof DirectedEdge : 'newEdge returns DirectedEdge' 
assert dgraph.edge() instanceof DirectedEdge : 'edge returns DirectedEdge' 

前兩個斷言顯示沒有DirectedGraph特徵的行爲。下一個特徵顯示了DirectedGraph的預期行爲,但特質的方法似乎沒有用在最後的斷言中。

最後一個斷言失敗。

Caught: java.lang.AssertionError: edge returns DirectedEdge. Expression: (dgraph.edge() instanceof DirectedEdge) 
java.lang.AssertionError: edge returns DirectedEdge. Expression: (dgraph.edge() instanceof DirectedEdge) 

我想知道如何解決這個問題,這樣最後的斷言可以通過。

回答

0

下面是def dgraph = new Graph() as DirectedGraph語義上發生的事情:

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

這種對象實現的性狀和代表所有未定義調用原始的對象,即Graph實例。

assert dgraph.newEdge() instanceof DirectedEdge工程因爲newEdge方法是從特質派生。
assert dgraph.edge() instanceof DirectedEdge失敗,因爲沒有edge方法,此調用委託給原始的Graph實例,而實例本身並沒有關於代理包裝器的知識。

這可以通過使用純類繼承來實現:

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

感謝您的幫助!這實際上填補了我的知識中的很多空白。我可能會去像這樣的東西 graph.metaClass.newEdge = { - > 收益曲線和新際()withTraits(DirectedEdge) 。} 這是爲了避免複雜性增加的重量和屬性時。 –

+0

@JohnMercier不客氣!我建議不要用元類魔法,請考慮繼承。你可以提供更多關於你想要達到的細節,所以我可以用另一種解決方案來幫助你。 – Dany

+0

我不確定繼承會起作用。這是項目https://github.com/moaxcp/graph-dsl。我的目標是製作一個帶有圖形的腳本作爲代表。我想使用apply方法將圖更改爲有向圖很容易。 –

相關問題