可以将地图强制设置为委托吗?

时间:2019-06-06 23:38:06

标签: groovy metaprogramming

我正在使用Groovy的运行时元编程工具构建一个简单的psuedo-xml构建器。我建立了一个可以成功完成此操作的类,但是当我尝试通过将映射强制到接口中尝试其他方法时,遇到了Groovy methodMissing设备的问题。

我尝试过的方法是将包含methodMissing的{​​{1}}键的映射强制转换为已定义ClosuremethodMissing的接口

这是主要的:

GroovyObject

builder(有效):

mybuilder = new builder() //good
mybuilder.xml = { ->
    thelettersofdaalpabet {
        "q"
    }
}

mycoercionbuilder = new coercionbuilder() //errors out
mycoercionbuilder.messages = { ->
    thelettersofdaalpabet {
        "q"
    }
}

和coercionbuilder(会出错):

class builder {
    def methodMissing(String methodName, args){
        println "<$methodName>"
        for(Closure c : args){
            c.delegate = this
            def out = c()
            if (out != null) println out
        }
        println "</$methodName>"
    }

    def propertyMissing(String propName, val) {
        this.methodMissing(propName,val)
    }
}

这是coercionbuilder中提到的builderrules界面:

class coercionbuilder {
    def b = [
            methodMissing: { String methodName, args ->
                println "<$methodName>"
                for (Closure c : args) {
                    c.delegate = b
                    def out = c()
                    if (out != null) println out
                }
                println "</$methodName>"
            }] as builderrules //<-- I also changed this value to GroovyObject

    def propertyMissing(String propName, val) {
        this.b.methodMissing(propName, val)
    }
}

将地图强制转换为构建器规则后,其输出:

interface builderrules {
    def methodMissing(String methodName, args)
}

将地图强制转换为GroovyObject时,其输出:

<xml>
<thelettersofdaalpabet>
q
</thelettersofdaalpabet>
</xml>
<messages>
Caught: groovy.lang.MissingMethodException: No signature of method: main.thelettersofdaalpabet() is applicable for argument types: (main$_run_closure2$_closure4) values: [main$_run_closure2$_closure4@ba47ffaf]
groovy.lang.MissingMethodException: No signature of method: main.thelettersofdaalpabet() is applicable for argument types: (main$_run_closure2$_closure4) values: [main$_run_closure2$_closure4@ba47ffaf]
    at main$_run_closure2.doCall(main.groovy:10)
    at coercionbuilder$_closure1.doCall(coercionbuilder.groovy:7)
    at com.sun.proxy.$Proxy14.methodMissing(Unknown Source)
    at builderrules$methodMissing.call(Unknown Source)
    at coercionbuilder.propertyMissing(coercionbuilder.groovy:14)
    at coercionbuilder.setProperty(coercionbuilder.groovy)
    at main.run(main.groovy:9)

1 个答案:

答案 0 :(得分:0)

这里只是从臀部射击,但是您是否尝试过将闭合解决策略设置为DELEGATE_FIRST:

...
                for (Closure c : args) {
                    c.delegate = b
                    c.resolveStrategy = Closure.DELEGATE_FIRST
                    def out = c()
                    if (out != null) println out
                }
...