首页 文章

为什么在Groovy闭包中设置的实例变量的值在其外部不可见?

提问于
浏览
3

Question

为什么 methodA() 打印 set within run 而不是 set within closure

Code example

class GroovyClosureVariableScopingTest extends Script {

    String s

    Object run() {
        s = "set within run"
        println "value of s in run(): $s"

        [1].each {
            s = "set within closure"
            println "value of s in each()-closure: $s"
            methodA()
        }
    }

    void methodA() {
        println "value of s in methodA(): $s"
    }
}

Actual output

value of s in run(): set within run
value of s in each()-closure: set within closure
value of s in methodA(): set within run            // <- Surprised to see the original value

Expected output

value of s in run(): set in run
value of s in each()-closure: set within closure
value of s in methodA(): set within closure        // <- Whould have expected this value

Elaboration

我还不太清楚变量作用域如何在上面的例子中起作用 . 我本来期望 s 是该类的属性(公共实例变量),我认为我从 each -closure中分配了一个值,该值将被保留 . 但事实似乎并非如此 .

为什么 s 不保留在闭包内分配的值?

Solution / workaround

s 作为参数传递给 methodA() 有效 . 请参阅注释 // Change 的行 .

class GroovyClosureVariableScopingTest extends Script {

    String s

    Object run() {
        s = "set within run"
        println "value of s in run(): $s"

        [1].each {
            s = "set within closure"
            println "value of s in each()-closure: $s"
            methodA(s)              // Change
        }
    }

    void methodA(s) {               // Change
        println "value of s in methodA(): $s"
    }
}

Reference

Closures - Formal Definition

同时,变量仍然可以正常地用于封闭范围,因此闭包可以读取/更改任何此类值,并且外部范围的代码可以读取/更改相同的变量 .

Versions

  • Groovy 1.8.6

  • Groovy-Eclipse插件2.8.0

  • Eclipse Platform 3.8.1

1 回答

  • 0

    用户cfrick确认它在他的机器上工作后,我从控制台运行它确实有效 .

    From console

    C:\temp>java -jar C:\...\lib\groovy-all-1.8.6.jar C:\temp\GroovyClosureVariableScopingTest.groovy
    value of s in run(): set within run
    value of s in each()-closure: set within closure
    value of s in methodA(): set within closure // <- Here
    

    With clean Eclipse installation

    但我仍然没有得到原始脚本与干净安装运行

    Summary

    我仍然不知道为什么它不起作用 - 即使是干净的Eclipse安装 . 但是,它可以在控制台上运行,它可以在cfrick的机器上运行,并且有一个解决方法 .

相关问题