[英]In order for a groovy closure to modify a variable defined in the scope of a delegate, do you need to explicitly specify delegate.theVariableName?
我偶然發現Groovy關閉和代表的事情,我不確定是該語言的官方部分,甚至可能是一個錯誤。
基本上我定義了一個閉包,我將其作為來自外部源的字符串讀入,並且類中定義閉包的變量之一需要由閉包修改。 我寫了一個簡單的例子,展示了我發現的東西,什么不起作用。
如果查看下面的測試代碼,您將看到一個定義變量的類
animal = "cat"
和動態定義的兩個閉包試圖修改動物變量。
這工作>
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
但事實並非如此
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
看來我需要使用'delegate'明確限定我的待修改變量。 為此工作。 (我想我也可以在封閉類中定義一個setter,以便閉包調用以修改值。)
所以....我已經找到了如何使這項工作,但我有興趣,如果有人可以指向我一些groovy doc解釋其背后的規則。
具體來說....為什么簡單的任務
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'
}
}
OWNER_FIRST
:首先檢查所有者(定義閉包的位置),然后檢查委托 OWNER_ONLY
:檢查所有者,僅在明確引用時檢查委托 DELEGATE_FIRST
:首先檢查委托,然后檢查所有者 DELEGATE_ONLY
:首先檢查委托,僅在顯式引用時檢查所有者 TO_SELF
:既不檢查委托也不檢查所有者 默認值為OWNER_FIRST
。 由於閉包是動態定義的,因此您的所有者是一個Script對象,它本身具有特殊規則。 在Script中編寫animal = 'bear'
實際上會創建一個名為animal
的新綁定並為其分配'bear'
。
您可以通過簡單地更改閉包上的解析策略,然后在調用它之前修復您的測試,而無需顯式引用委托:
closure.resolveStrategy = Closure.DELEGATE_FIRST
這將避免奇怪的腳本綁定並按預期使用委托。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.