Groovyのクロージャーとデリゲートを使って何かに遭遇しましたが、私はその言語の公式な部分か、おそらくバグだとは確信していません。groovyクロージャがデリゲートのスコープで定義された変数を変更するには、delegate.theVariableNameを明示的に指定する必要がありますか?
私は、外部ソースからの文字列として読み込んだクロージャーを定義しています。 クロージャーを定義するクラス内の変数の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'
}
}
これは理にかなっています。速すぎる; ^)。本当にありがとう。 –