为了让 groovy 闭包修改在委托范围内定义的变量,是不是需要显式指定 delegate.theVariableName?
Posted
技术标签:
【中文标题】为了让 groovy 闭包修改在委托范围内定义的变量,是不是需要显式指定 delegate.theVariableName?【英文标题】: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 闭包修改在委托范围内定义的变量,是否需要显式指定 delegate.theVariableName? 【发布时间】:2012-08-25 15:56:44 【问题描述】:我偶然发现了一些带有 Groovy 闭包和委托的东西,我不确定它是否是该语言的官方部分,甚至可能是一个错误。
基本上,我定义了一个闭包,我将其作为来自外部源的字符串读入, 并且类中定义闭包的变量之一需要被闭包修改。我写 一个简单的例子,展示了我发现什么有效,什么无效。
如果您查看下面的测试代码,您会看到一个定义变量的类
animal = "cat"
和两个试图修改动物变量的字符串动态定义的闭包。
这行得通>
String code = " -> delegate.animal = 'bear'; return name + 'xx' ; "
但这不是
String code = " -> animal = 'bear'; return name + 'xx' ; "
似乎我需要使用“委托”明确限定我的待修改变量。为此工作。 (我想我也可以在封闭类中定义一个 setter 来调用闭包来修改值。)
所以.... 解释这背后的规则的文档。
具体....为什么会简单赋值
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'
【问题讨论】:
【参考方案1】:Groovy 闭包有 five strategies 用于解析闭包内的符号:
OWNER_FIRST
:首先检查所有者(定义闭包的地方),然后检查委托
OWNER_ONLY
:检查所有者,仅在明确引用时检查委托
DELEGATE_FIRST
:先检查delegate,再检查owner
DELEGATE_ONLY
:首先检查委托,仅在明确引用时检查所有者
TO_SELF
:委托和所有者都没有被检查
默认为OWNER_FIRST
。由于闭包是动态定义的,因此您的所有者是一个本身具有特殊规则的脚本对象。在脚本中写入animal = 'bear'
实际上会创建一个名为animal
的新绑定,并将'bear'
分配给它。
您可以在不显式引用委托的情况下修复您的测试,只需在调用之前更改闭包上的解析策略:
closure.resolveStrategy = Closure.DELEGATE_FIRST
这将避免奇怪的脚本绑定并按预期使用委托。
【讨论】:
以上是关于为了让 groovy 闭包修改在委托范围内定义的变量,是不是需要显式指定 delegate.theVariableName?的主要内容,如果未能解决你的问题,请参考以下文章
Javascript命名空间 - 如何根据命名导出函数范围内定义的函数和变量?