Groovyのクロージャとデリゲートのあるものに出くわしましたが、それが言語の公式な部分であるか、おそらくバグであるかはわかりません。
基本的に、外部ソースから文字列として読み込んだクロージャを定義しています。クロージャを定義するクラスの変数の1つは、クロージャによって変更する必要があります。何がうまくいくか、何がうまくいかないかを示す簡単な例を書きました。
以下のテストコードを見ると、変数を定義するクラスがあります。
animal = "cat"
動物変数を変更しようとする文字列からその場で定義された2つのクロージャ。
これは機能します>
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
しかし、これはしません
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
変更する変数を「デリゲート」で明示的に修飾する必要があるようです。これが機能するために。(値を変更するためにクロージャーが呼び出すために、囲んでいるクラスにセッターを定義することもできると思います。)
だから....私はこれを機能させる方法を見つけましたが、誰かが私にこの背後にあるルールを説明するグルーヴィーなドキュメントを教えてくれるかどうか興味があります。
具体的には....なぜ単純な割り当てになるのでしょうか
animal = 'bear'
元の変数に影響しますか?ここでシャドウコピーが作成されていますか?
import org.junit.Test
/*
* Author: cbedford
* Date: 8/30/12
* Time: 1:16 PM
*/
class GroovyTest {
String animal = "cat"
String name = "fred"
@Test
public void testDelegateWithModificationOfDelegateVariable() {
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
def shell = new GroovyShell()
def closure = shell.evaluate(code)
closure.delegate = this
def result = closure()
println "result is $result"
println "animal is $animal"
assert animal == 'bear'
assert result == 'fredxx'
}
// This test will FAIL.
@Test
public void testDelegateWithFailedModificationOfDelegateVariable() {
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
def shell = new GroovyShell()
def closure = shell.evaluate(code)
closure.delegate = this
def result = closure()
println "result is $result"
println "animal is $animal"
assert animal == 'bear'
assert result == 'fredxx'
}
}