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

时间:2014-09-11 07:20:48

标签: groovy scope closures

问题

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

代码示例

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"
    }
}

实际输出

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

预期输出

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

精化

我还没有完全理解变量作用域如何在上面的例子中起作用。我原以为s是该类的一个属性(一个公共实例变量),我认为我在each - 闭包中赋予它一个值,该值将被保留。但情况似乎并非如此。

为什么s没有保留在闭包中分配的值?

解决方案/解决方法

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"
    }
}

参考

Closures - Formal Definition

  

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

版本

  • Groovy 1.8.6
  • Groovy-Eclipse插件2.8.0
  • Eclipse Platform 3.8.1

1 个答案:

答案 0 :(得分:0)

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

从控制台

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

使用干净的Eclipse安装

但我仍然没有通过干净的

安装来运行原始脚本

<强>摘要

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