微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为了使groovy闭包修改委托范围中定义的变量,是否需要显式指定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'
    }
}

解决方法

Groovy闭包有 five strategies用于解析闭包内的符号:

> OWNER_FirsT:首先检查所有者(定义闭包的位置),然后检查委托
> OWNER_ONLY:检查所有者,仅在明确引用时检查委托
> DELEGATE_FirsT:首先检查委托,然后检查所有者
> DELEGATE_ONLY:首先检查委托,仅在明确引用时检查所有者
> TO_SELF:既未检查委托也未检查所有者

认值为OWNER_FirsT.由于闭包是动态定义的,因此您的所有者是一个Script对象,它本身具有特殊规则.在Script中编写animal =’bear’实际上会创建一个名为animal的新绑定并为其分配’bear’.

您可以通过简单地更改闭包上的解析策略,然后在调用它之前修复您的测试,而无需显式引用委托:

closure.resolveStrategy = Closure.DELEGATE_FirsT

这将避免奇怪的脚本绑定并按预期使用委托.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐