如何在Trait中调用时正确使用闭包委托

时间:2016-08-17 13:00:43

标签: groovy

我有一个Groovy特性需要提供一个配置Closure作为库方法调用的参数(它是HttpBuilder,但它应该没关系)。

为了重现这个问题,我创建了以下简单示例:

trait T {
    def doIt() {
        return {
            n = 1
        }
    }
}

class Delegate {
    int n
}

class Tish implements T {
    def go() {
        def closure = doIt()
        def d = new Delegate()
        closure.delegate = d
        closure()
        assert d.n == 1
    }
}

new Tish().go()

预计这会运行没有错误,因为当运行doIt()特征中的T方法返回的闭包时,其委托被设置为可以设置n变量的东西到1 ....

但是,这不起作用,我收到此错误:

 groovy.lang.MissingPropertyException: No such property: n for class: Tish

如果我将T作为一个课程,让Tish代替它,那么它就可以了!

我尝试更改Closure的委托策略,但这没有帮助。

这是一个Groovy错误还是有办法解决这个问题?

2 个答案:

答案 0 :(得分:1)

好吧,我找到了一个解决方法......但是,知道这是一个bug是否很有趣,如果是,那么什么时候Groovy团队会修复它!

更新this is a bug并希望在不久的将来修复Groovy版本!

在config Closure中进行的所有调用都可以通过调用getDelegate()方法获取实际的Delegate对象,然后直接在其上设置所有属性,如下所示:

return {
    def d = getDelegate()
    d.n = 1
}

不理想,但让我失望,希望它能帮助别人......

编辑: 正如@bdkosher在评论中所指出的,另一个解决方案是在闭包中使用setter语法:

return {
    setN 1
}

答案 1 :(得分:0)

更改代码
<canvas id="canvas"></canvas>

def d = new Delegate()
closure.delegate = d
closure()

这解决了一个非常相似的问题,我在Grails 3.3.8,Groovy 2.4.15,Java 1.8.0_131中遇到过。不知道为什么,但是有帮助。

我正试图找出错误并添加以下输出

def d = new Delegate()
closure.delegate = d
closure.run()

并发现在第一种情况下,println this println owner println delegate 甚至在执行delegate之前就已经设置closure.delegate = d都没有改变!如果调用了closure(),那么closure.run()的设置正确!!!