为什么边缘不返回DirectedEdge?

时间:2017-01-22 03:52:51

标签: groovy

使用特征时遇到了问题。以下代码使用特征覆盖newEdge。

#!/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)

我想知道如何解决这个问题,以便最后一个断言可以通过。

1 个答案:

答案 0 :(得分: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