Chr*_*ord 8 groovy closures scope
我偶然发现Groovy关闭和代表的事情,我不确定是该语言的官方部分,甚至可能是一个错误.
基本上我定义了一个闭包,我将其作为来自外部源的字符串读入,并且类中定义闭包的变量之一需要由闭包修改.我写了一个简单的例子,展示了我发现的东西,什么不起作用.
如果查看下面的测试代码,您将看到一个定义变量的类
animal = "cat"
Run Code Online (Sandbox Code Playgroud)
和动态定义的两个闭包试图修改动物变量.
这工作>
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
Run Code Online (Sandbox Code Playgroud)
但事实并非如此
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
Run Code Online (Sandbox Code Playgroud)
看来我需要使用'delegate'明确限定我的待修改变量.为此工作.(我想我也可以在封闭类中定义一个setter,以便闭包调用以修改值.)
所以....我已经找到了如何使这项工作,但我有兴趣,如果有人可以指向我一些groovy doc解释其背后的规则.
具体来说....为什么简单的任务
animal = 'bear'
Run Code Online (Sandbox Code Playgroud)
影响原始变量?是否有阴影副本在这里制作?
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'
}
}
Run Code Online (Sandbox Code Playgroud)
OWNER_FIRST
:首先检查所有者(定义闭包的位置),然后检查委托OWNER_ONLY
:检查所有者,仅在明确引用时检查委托DELEGATE_FIRST
:首先检查委托,然后检查所有者DELEGATE_ONLY
:首先检查委托,仅在明确引用时检查所有者TO_SELF
:既不委托代表也不检查所有者 默认是OWNER_FIRST
.由于闭包是动态定义的,因此您的所有者是一个Script对象,它本身具有特殊规则.编写animal = 'bear'
一个脚本实际上会创建一个新的名为绑定animal
并分配'bear'
给它.
您可以通过简单地更改闭包上的解析策略,然后在调用它之前修复您的测试,而无需显式引用委托:
closure.resolveStrategy = Closure.DELEGATE_FIRST
Run Code Online (Sandbox Code Playgroud)
这将避免奇怪的脚本绑定并按预期使用委托.