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

ama*_*ion 33 groovy scope

我有一个关于Groovy中的作用域规则的问题.在下面的代码片段中,我有三个变量,a具有本地范围,b具有脚本范围,并且c还应使用@Field注释获取脚本范围.

#!/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();
Run Code Online (Sandbox Code Playgroud)

我得到MissingPropertyException了评论所示的界限.a期望例外,因为该变量具有局部范围.但我希望b可以在里面访问method()- 事实并非如此. @Field在groovy 1.8.6中没有做任何事情,虽然升级后它起作用,所以我猜这是一个老bug.然而,任何一个版本c内部都无法访问method().

所以我的问题是:

  1. 为什么我不能访问带有@Field内部 注释的变量method()
  2. 我怎样才能引用里面的脚本变量method()

ata*_*lor 30

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

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

  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();
Run Code Online (Sandbox Code Playgroud)


tim*_*tes 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() {
  }
}
Run Code Online (Sandbox Code Playgroud)