我对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。然而,c
内method()
无法访问任何版本。{/ p>
所以我的问题是:
@Field
注释的变量
method()
? method()
?答案 0 :(得分:29)
如果在groovy脚本中有class
声明之外的方法或语句,则会创建隐式类。回答你的问题:
在您的示例中,func()
可以访问字段c
,因为它们都是隐式类的成员。 Main
类不是,所以不能。
您需要将对脚本变量的引用传递给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();
答案 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() {
}
}