Groovy范围 - 如何在方法中访问脚本变量

时间:2013-03-25 15:54:53

标签: groovy scope

我对Groovy中的作用域规则有疑问。在以下代码段中,我有三个变量,a具有本地范围,b具有脚本范围,c也应使用@Field注释获取脚本范围。< / p>

#!/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。期望a上的例外,因为该变量具有局部范围。但我希望b可以在method()内访问 - 但事实并非如此。 @Field在groovy 1.8.6中没有做任何事情,虽然升级后它可以工作,所以我想这是一个老bug。然而,cmethod()无法访问任何版本。{/ p>

所以我的问题是:

  1. 为什么我无法访问内部带有@Field注释的变量 method()
  2. 如何在method()
  3. 中引用脚本变量

2 个答案:

答案 0 :(得分:29)

如果在groovy脚本中有class声明之外的方法或语句,则会创建隐式类。回答你的问题:

  1. 在您的示例中,func()可以访问字段c,因为它们都是隐式类的成员。 Main类不是,所以不能。

  2. 您需要将对脚本变量的引用传递给method()。一种方法是传递隐式定义的binding对象,通过该对象可以访问所有脚本范围变量。

  3. 示例:

    #!/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();
    

答案 1 :(得分: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() {
  }
}