簡體   English   中英

為了使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關閉和代表的事情,我不確定是該語言的官方部分,甚至可能是一個錯誤。

基本上我定義了一個閉包,我將其作為來自外部源的字符串讀入,並且類中定義閉包的變量之一需要由閉包修改。 我寫了一個簡單的例子,展示了我發現的東西,什么不起作用。

如果查看下面的測試代碼,您將看到一個定義變量的類

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閉包有五種解決閉包內符號的策略

  • 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM