2013-03-25 49 views
26

我有一個關於Groovy中的範圍規則的問題。在下面的片段中,我有三個變量,a具有本地範圍,b具有腳本範圍,並且c也應該使用@Field註釋來獲取腳本範圍。Groovy範圍 - 如何在方法中訪問腳本變量

#!/usr/bin/groovy 
import groovy.transform.Field; 

//println org.codehaus.groovy.runtime.InvokerHelper.getVersion() 

def a = 42; 
b = "Tea" 
@Field def c = "Cheese" 

void func() 
{ 
    // println a // MissingPropertyException 
    println b // prints "Tea" 
    println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6 

} 

class Main 
{ 
    def method() 
    { 
     // println a // MissingPropertyException 
     // println b // MissingPropertyException 
     // println c // MissingPropertyException with both 1.8.6. and 2.1.2 
    } 

} 

func(); 
new Main().method(); 

我得到MissingPropertyException s在註釋表示的行上。預計有a的例外情況,因爲該變量具有本地範圍。但我期望b可以在method()之內訪問 - 事實並非如此。 @Field在groovy 1.8.6中沒有做任何事情,雖然在升級之後它可以工作,所以我猜這是一個老bug。儘管如此,cmethod()的任何一個版本中都無法訪問。

所以我的問題是:

  1. 爲什麼我不能訪問標註有@Fieldmethod()變量?
  2. 如何參考method()中的腳本變量?

回答

25

當您在groovy腳本中聲明class以外的方法或語句時,會創建一個隱式類。要回答你的問題:

  1. 在你的榜樣,因爲他們是隱含類的成員func()可以訪問現場cMain類不是,所以它不能。

  2. 您需要將腳本變量的引用傳遞給method()。一種方法是通過隱式定義的binding對象,通過它可以訪問所有腳本作用域變量。

實施例:

#!/usr/bin/groovy 
import groovy.transform.Field; 

//println org.codehaus.groovy.runtime.InvokerHelper.getVersion() 

def a = 42; 
b = "Tea" 
@Field def c = "Cheese" 

void func() 
{ 
    // println a // MissingPropertyException 
    println b // prints "Tea" 
    println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6 

} 

class Main 
{ 
    def scriptObject 
    def binding 

    def method() 
    { 
     // println a // MissingPropertyException 
     println binding.b 
     println scriptObject.c 
    } 
} 

func(); 
new Main(scriptObject: this, binding: binding).method(); 
+0

敢肯定你的意思是通過這些scriptObject和綁定參數構造函數,一拉「新的主(scriptObject:此,結合:結合)。方法() 「 – billjamesdev 2013-03-27 18:16:50

+0

哎呀,謝謝。糾正。 – ataylor 2013-03-27 18:31:13

9

該腳本和Main作爲同一文件內兩個獨立的類生成。

由於Main不是Script類的內部類,所以在腳本類中看不到java.lang.Object c字段。

你要麼必須明確地包裝這個腳本的類與static main(args)方法(和內部Main類),或者你需要的腳本類的實例傳遞給像方法:Main.method(this)

這是諸如此類的事情,上面的腳本生成:

class Script032034034 { 
    Object c 

    Script032034034() { 
    c = 'Cheese' 
    } 

    Object run() { 
    Object a = 42 
    b = 'Tea' 
    func() 
    new Main().method() 
    } 

    void func() { 
    println b 
    println c 
    } 
} 

class Main { 
    Object method() { 
    } 
} 
+0

感謝生成的代碼片段,這有助於我的理解。我的誤解是,我認爲Main是Script032034034的一個子類。 – amarillion 2013-03-25 16:39:45

+0

真正有用的一段代碼。謝謝:) – 2017-03-16 20:25:22

+1

在你提供的代碼中,'func()'「看到」b「怎麼樣? 'b'也是Script類的屬性嗎? – 2017-06-16 17:48:14