2014-09-11 40 views
3

問題爲什麼在Groovy閉包中設置的實例變量的值在外面不可見?

爲什麼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 -closure內的值賦給它。但似乎並非如此。

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平臺3.8.1
+1

這是什麼groovy版本,你如何運行這個類的代碼?與'2.3.6'和一個稍微簡單的版本,我得到了預期的結果。與您的代碼(不擴展'腳本')它也按預期工作) – cfrick 2014-09-11 08:11:10

+0

@cfrick我已經將信息添加到上述問題。 – Lernkurve 2014-09-11 08:18:40

+0

不妨是舊版本的verison或者那裏的一個bug。你用'setS(...)'試過了嗎? – cfrick 2014-09-11 08:41:10

回答

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 4.3運行開普勒
  • Groo VY Eclipse插件​​3210
  • Groovy編譯1.8.x的,也2.3.4

摘要

我仍然不知道爲什麼它不工作 - 甚至用乾淨的安裝蝕。 但是,它在控制檯上工作,它在cfrick的機器上工作,並且有一種解決方法。

+0

在Eclipse中運行進程之後,轉到調試透視圖並打開已終止進程的上下文菜單。兩個節點之一應該有一個條目「屬性」。如果選擇它,那麼你可以看到Eclipse使用的類路徑。 1.在類路徑中查找任何奇怪的東西。 2.從控制檯嘗試相同的類路徑。 – 2014-09-18 07:31:45

相關問題