Question
Why does methodA()
print set within run
instead of 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
I haven't quite understood how variable scoping works in the above example. I would have expected s
to be a property (a public instance variable) of the class and I thought that I was assigning it a value from within the each
-closure which would be retained. But that does not seem to be the case.
Why does s
not keep the value which it was assigned from within the closure?
Solution / workaround
Passing s
as argument to methodA()
works. See lines commented with // 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
At the same time, the variables are still available normally to the enclosing scope, so the closure may read/change any such values, and code from the outer scope may read/change the same variables.
Versions
After user cfrick confirmed that it works on his machine, I ran it from the console and it indeed works.
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
But I still don't get the original script to run with a clean installation of
Summary
I still don't know why it doesn't work -- even with a clean installation of Eclipse. However, it works from the console, it works on cfrick's machine and there is a workaround.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.