自动属性getter,局部变量和闭包之间的Groovy冲突?

Wil*_*ris 6 groovy closures properties

Groovy似乎有一些非常不愉快的行为与"Groovy Beans"和闭包有关,这些行为可能导致它在某些情况下掩盖局部变量.

这是已知的行为,是否有某些文档可以详细说明这些内容?我浪费了很多时间试图弄清楚什么不起作用......

请考虑以下代码:

class TestClass {

    def doIt(Closure closure) {
        closure.setDelegate(this)
        closure.call()
    }

    def getRevision() {
        return "testclass revision"
    }
}

def testIt() {
    def revision = "testit revision"

    println "1: " + revision + " (expect: testit)"

    TestClass tester = new TestClass()
    tester.doIt {
        println "2: " + getRevision()  + " (expect: testclass)"
    }

    println "3: " + revision + " (expect: testit)"

    tester.doIt {
        println "4: " + revision + " (expect: testit)"
        revision = getRevision()
        println "5: " + revision + " (expect: testclass)"
        println "6: ${getRevision()} (expect: testclass)"
        println "7: " + getRevision() + " (expect: testclass)"
    }

    // expect to have been set to testclass value in previous closure
    println "8: " + revision + " (expect: testclass)"

    tester.doIt {
        println "9: ${getRevision()} (expect: testclass)"
        println "10: " + getRevision() + " (expect: testclass)"
    }

    println "11: " + revision + " (expect: testclass)"
}

testIt()
Run Code Online (Sandbox Code Playgroud)

运行此代码将生成以下输出:

1: testit revision (expect: testit)
2: testclass revision (expect: testclass)
3: testit revision (expect: testit)
4: testit revision (expect: testit)
5: testit revision (expect: testclass)
6: testit revision (expect: testclass)
7: testit revision (expect: testclass)
8: testit revision (expect: testclass)
9: testclass revision (expect: testclass)
10: testclass revision (expect: testclass)
11: testit revision (expect: testclass)
Run Code Online (Sandbox Code Playgroud)

我的主要问题是5/6/7.似乎只是revision在闭包中使用局部变量"隐藏" getRevision()委托中的方法,并将其替换为自动生成的bean样式getRevision()以匹配revision"属性".如果我不使用revision变量,则调用getRevision()不调用此bean行为.

任何洞察或文档链接将不胜感激!

ig0*_*774 1

Groovy 闭包有一个resolveStrategy可用于控制解析顺序的属性。默认策略是从“拥有”对象中查找属性,并且只有在找不到该属性时才使用委托。我相信将其设置为DELEGATE_FIRST会得到您期望的行为。