通常需要在脚本顶部声明常量,这些常量可以在脚本中的任何其他位置引用。在Groovy中,似乎如果使用final声明一个常量,那么它在子范围内是不可访问的。这个非常基本和常见的要求是什么解决方案?我现在的解决方法是创建一个未绑定的变量,但这不是常量而且不优雅。
答案 0 :(得分:77)
Groovy并不具备全局范围。如果你有一个没有声明类的groovy脚本,它会隐藏在一个带有脚本名称的类中。因此,顶级范围内的最终变量实际上只是隐式类的字段。例如:
// foo.groovy
final MYCONSTANT = "foobar"
println MYCONSTANT
class Helper {
def hello() { println MYCONSTANT } // won't work
}
new Helper().hello()
或多或少等同于:
class foo {
def run() {
final MYCONSTANT = "foobar"
println MYCONSTANT
new Helper().hello()
}
static main(args) {
new foo().run()
}
}
class Helper {
def hello() { println MYCONSTANT } // won't work
}
很容易理解为什么扩展不起作用。一个简单的解决方法是在一个虚拟类中声明你的“全局”,例如常量,然后只需对其进行静态导入。它甚至可以在一个脚本中运行。例如:
import static Constants.*
class Constants {
static final MYCONSTANT = "foobar"
}
println MYCONSTANT
class Helper {
def hello() { println MYCONSTANT } // works!
}
new Helper().hello()
编辑:
此外,脚本有点特殊情况。如果您声明一个没有def
的变量或任何修饰符(例如final
)(即只使用它),它将进入一个脚本范围的绑定。所以在这种情况下:
CONSTANT = "foobar"
println "foobar"
CONSTANT在脚本范围内绑定,但在:
final CONSTANT = "foobar"
println "foobar"
CONSTANT是脚本run()
方法中的局部变量。有关这方面的更多信息,请访问https://web-beta.archive.org/web/20150108090004/http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22
答案 1 :(得分:21)
在Groovy 1.8+中,您可以使用@Field
annotation:
import groovy.transform.Field
@Field final String MY_CONSTANT = 'constant'
def printConstant() { println MY_CONSTANT }
printConstant()
答案 2 :(得分:0)
添加全局应用程序级常量的另一种有效方法是 在合适的包中声明一个接口
interface applicationConstants {
//All constants goes here.
static final float PI = 3.14
String ADMIN_USER = "ADMIN"
Map languages = [
"en": "English",
"hi": "Hindi",
"mr": "Marathi"
]
// Like above you can declare all application level code constants here.
}
在任何类中使用常量,如下所示
import packageNameContainingInterface.applicationConstants // import statement.
def adminUser = applicationConstants.ADMIN_USER
println adminUser
答案 3 :(得分:0)
我个人不会这样做,但是从技术上讲您可以做到
Object.metaclass.MYCONSTANT = 'foobar'
然后每个对象都拥有它