Groovy resolve嵌套闭包中的策略

时间:2019-10-11 07:17:49

标签: groovy

我对嵌套闭包中的Groovy委派策略感到困惑。这是一个简化的示例:

class Clazz {
    String name
    String whoAmI() {
        return name
    }
    void doit(Clazz clazz) {
        def cl = {
            println "Outer closure: resolveStrategy=${resolveStrategy}, " +
                    "implicit=${whoAmI()}, delegated=${delegate.whoAmI()}"
            {->
                println "Inner closure: resolveStrategy=${resolveStrategy}, " +
                        "implicit=${whoAmI()}, delegated=${delegate.whoAmI()}"
            }.call()
        }
        cl.resolveStrategy = Closure.DELEGATE_FIRST
        cl.delegate = clazz
        cl()
    }
}

def a = new Clazz(name: 'A')
def b = new Clazz(name: 'B')
a.doit(b)

输出:

  

外部闭包:resolveStrategy = 1,隐式= B,委托= B

     

内部闭包:resolveStrategy = 0,隐式= A,委托= B

为什么 resolveStrategy 不能传播到内部闭包?设置解决方案策略的目的是改变隐式 this 的解决方式。但是,如果它没有在闭包内部传播,那么该机制似乎和无用一样好。在Groovy中,闭包是如此普遍,以至于没有它们,几乎很难写几行。

1 个答案:

答案 0 :(得分:1)

大约五年前发现了一个类似的问题:Nested closure resolution different between methods and properties?显然是一个错误,此后一直没有任何动静地打开过:https://issues.apache.org/jira/browse/GROOVY-7232

链接的帖子中还提到了一些我也注意到的内容:属性已正确解析为委托,但不是方法调用。这是一个经过重做的示例来证明这一点:

class Clazz {
    String name

    void doit(Clazz clazz) {
        def cl = {
            println "Outer closure: property=${name}, method=${getName()}"
            {->
                println "Inner closure: property=${name}, method=${getName()}"
            }.call()
        }
        cl.resolveStrategy = Closure.DELEGATE_FIRST
        cl.delegate = clazz
        cl()
    }
}

def a = new Clazz(name: 'A')
def b = new Clazz(name: 'B')
a.doit(b)

结果:

Outer closure: property=B, method=B
Inner closure: property=B, method=A

链接帖子中的某人使用 rehydrate 发布了一种解决方法。就我而言,它只有在替换了所有引用(包括 this

)时才起作用(某种程度上)!
class Clazz {
    String name

    void doit(Clazz clazz) {
        def cl = {
            println "Outer closure: property=${name}, method=${getName()}"
            {->
                println "Inner closure: property=${name}, method=${getName()}"
            }.call()
        }
        cl.rehydrate(clazz, clazz, clazz)()
    }
}

def a = new Clazz(name: 'A')
def b = new Clazz(name: 'B')
a.doit(b)

结果:

Outer closure: property=B, method=B
Inner closure: property=B, method=B