Groovy作用域-如何访问方法中的脚本变量

Groovy作用域-如何访问方法中的脚本变量,groovy,scope,Groovy,Scope,我有一个关于Groovy中的作用域规则的问题。在下面的代码片段中,我有三个变量,a有局部作用域,b有脚本作用域,c也应该使用@字段注释获得脚本作用域 #!/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()

我有一个关于Groovy中的作用域规则的问题。在下面的代码片段中,我有三个变量,
a
有局部作用域,
b
有脚本作用域,
c
也应该使用
@字段
注释获得脚本作用域

#!/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中没有做任何事情,尽管升级后它可以工作,所以我想这是一个老错误。尽管如此,
c
method()
的任何版本中都是不可访问的

因此,我的问题是:

  • 为什么我不能访问内部带有
    @Field
    注释的变量
    method()
  • 如何引用
    method()
    中的脚本变量

  • 当groovy脚本中的
    声明之外有方法或语句时,将创建一个隐式类。回答您的问题:

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

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

  • 例如:

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

    此脚本和
    Main
    作为同一文件中的两个独立类生成

    由于
    Main
    不是脚本类的内部类,因此它无法看到脚本类中的
    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() {
      }
    }
    

    感谢生成的代码片段,这对我的理解有很大帮助。我的误解是,我认为Main将是Script032034034的一个子类。在您提供的代码中,
    func()
    如何“查看”
    b
    b
    也是Script类的一个属性吗?非常确定您的意思是将那些scriptObject和binding参数传递给构造函数,一个新的Main(scriptObject:this,binding:binding.method())