6

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()

このコードを実行すると、次の出力が生成されます。

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)

私の主な問題は、5/6/7 にあります。クロージャー内でローカルrevision変数を使用するだけで、デリゲートのメソッドが「非表示」になり、 「プロパティ」に一致するようにgetRevision()自動生成された Bean スタイルに置き換えられるようです。変数を使用しない場合、呼び出しはこの Bean の動作を呼び出しません。getRevision()revisionrevisiongetRevision()

ドキュメントへの洞察やリンクをいただければ幸いです。

4

1 に答える 1

1

Groovy クロージャーにはresolveStrategy、解決順序を制御するために使用できるプロパティがあります。デフォルトの戦略は、「所有する」オブジェクトからプロパティをルックアップし、そこに見つからない場合にのみデリゲートを使用することです。これを設定するDELEGATE_FIRSTと、期待どおりの動作が得られると思います。

于 2012-04-26T18:16:26.700 に答える