2011-02-01 306 views
36

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

回答

60

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" 

常数是在脚本范围内具有约束力,但在:

final CONSTANT = "foobar" 
println "foobar" 

常数是在脚本的run()方法的局部变量。更多相关信息可以在https://web-beta.archive.org/web/20150108090004/http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22

+0

常量应该是Java 1.5+世界中的枚举...... :) – Esko 2011-02-01 06:51:19

+6

@Esko每种类型的常量应该是一个枚举?甚至像重力或PI? O_o – 2011-02-01 07:34:38

18

发现在Groovy 1.8+,您可以使用@Field annotation实现这一点:

import groovy.transform.Field 

@Field final String MY_CONSTANT = 'constant' 

def printConstant() { println MY_CONSTANT } 

printConstant() 
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