groovy闭包Expando调用与显式

时间:2013-06-27 23:31:27

标签: groovy closures expando

如果我有一个附加到expando的闭包,并且闭包引用了expando上的值,就像这样......

def e = new Expando()
e.val = 'hi'
e.doit = { println delegate.val }
e.doit()

工作正常。并打印'hi'

如果我用长格式调用闭包

e.doit.call()​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

它会抛出错误

groovy.lang.MissingPropertyException: No such property: val for class: Script1
at Script1$_run_closure1.doCall(Script1.groovy:4)
at Script1$_run_closure1.doCall(Script1.groovy)
at Script1.run(Script1.groovy:6)

这是因为委托从e更改为脚本。为什么? 我认为e.doit()和e.doit.call()应该是相同的。

我可以手动更改代理 - 就像这样

def e = new Expando()
e.val = 'hi'
e.doit = { println delegate.val }
e.doit.delegate=e;
e.doit.call()​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

有关如何跳过委托的显式设置的任何想法?

1 个答案:

答案 0 :(得分:1)

是的,有一个更好的主意。

当您知道为Expando定义的闭包(动态方法)时,直接引用Expando实例(而不是委托),这只是一个动态bean。另一方面,当针对具体类进行测试时,相同的测试将产生预期结果:

def e = new Expando()
e.val = 'hi'
e.doit = {
    println delegate.class.name
    "$e.val Joseph"
}

assert e.doit() == 'hi Joseph'
assert e.doit.call() == 'hi Joseph'

class Test{
    String a
    def printA = {
        println delegate.class.name
        "$delegate.a Joseph"
    }
}
def test = new Test(a: 'hi')

assert test.printA() == 'hi Joseph'
assert test.printA.call() == 'hi Joseph'

注意两个案例中println的系统输出。