2013-03-25 51 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