Groovy中的全局常量

时间:2011-02-01 03:45:14

标签: groovy global-variables

通常需要在脚本顶部声明常量,这些常量可以在脚本中的任何其他位置引用。在Groovy中,似乎如果使用final声明一个常量,那么它在子范围内是不可访问的。这个非常基本和常见的要求是什么解决方案?我现在的解决方法是创建一个未绑定的变量,但这不是常量而且不优雅。

4 个答案:

答案 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'

然后每个对象都拥有它