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

Ren*_*ato 5 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()
Run Code Online (Sandbox Code Playgroud)

这应该没有错误地运行,因为当运行trait中的doIt()方法返回的闭包时T,它的委托被设置为可以将n变量设置为1的东西....

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

 groovy.lang.MissingPropertyException: No such property: n for class: Tish
Run Code Online (Sandbox Code Playgroud)

如果我创建T一个类并让它Tish扩展它,那么它的工作原理!

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

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

Ren*_*ato 2

好吧,我找到了一个解决方法...不过,了解这是否是一个错误以及如果是的话,Groovy 团队何时修复它会很有趣!

更新这是一个错误,希望在不久的将来在 Groovy 版本中得到修复!

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

return {
    def d = getDelegate()
    d.n = 1
}
Run Code Online (Sandbox Code Playgroud)

不太理想,但让我摆脱了困境,希望对其他人有帮助......

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

return {
    setN 1
}
Run Code Online (Sandbox Code Playgroud)