2011-02-01 40 views
36

A menudo se desea declarar constantes en la parte superior de una secuencia de comandos que se puede hacer referencia en cualquier otro lugar en la secuencia de comandos. En Groovy, parece que si declara una constante utilizando el final, entonces no se puede acceder en los ámbitos secundarios. ¿Cuál es la solución para este requisito muy básico y común? La solución alternativa que tengo ahora es crear una variable independiente pero esto no es una constante y no es elegante.Constantes globales en Groovy

Respuesta

60

Groovy no tiene realmente un alcance global. Cuando tienes un script groovy que no declara una clase, implícitamente se queda atascado en una clase con el nombre del script. Entonces, las variables finales en el ámbito de nivel superior son realmente solo campos de la clase implícita. Por ejemplo:

// foo.groovy 
final MYCONSTANT = "foobar" 
println MYCONSTANT 

class Helper { 
    def hello() { println MYCONSTANT } // won't work 
} 
new Helper().hello() 

es más o menos equivalente a:

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 
} 

Es fácil ver por qué no funciona expandió a cabo. Un trabajo fácil es declarar tus "globales" en una clase ficticia llamada p. Constantes, y luego solo haga una importación estática en él. Incluso funciona todo en una sola secuencia de comandos. Ejemplo:

import static Constants.* 

class Constants { 
    static final MYCONSTANT = "foobar" 
} 

println MYCONSTANT 

class Helper { 
    def hello() { println MYCONSTANT } // works! 
} 
new Helper().hello() 

EDIT:

Además, los scripts son poco de un caso especial. Si declara una variable sin def o cualquier modificador como final, (es decir, simplemente úsela), entra en un enlace de script completo. Así que en este caso:

CONSTANT = "foobar" 
println "foobar" 

CONSTANTE está en el guión de toda la unión, pero en:

final CONSTANT = "foobar" 
println "foobar" 

constante es una variable local en el método de la secuencia de comandos run(). Más información sobre esto se puede encontrar en https://web-beta.archive.org/web/20150108090004/http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22

+0

Las constantes deben ser enumeradas en el mundo Java 1.5+ ... :) – Esko

+6

@Esko cada tipo de constante debe ser un Enum? ¿Incluso algo como GRAVITY o PI? O_o –

+0

@tim_yates: No, una enumeración debe contener todas las constantes que están relacionadas entre sí. En su ejemplo, sería algo como 'CelestialObjectAttributes.GRAVITY' o' MathematicConstants.PI'. También se pueden importar para que no tenga que repetir el nombre de la enumeración y las enumeraciones siempre son máquinas virtuales (* o classloader *) globales, lo que las convierte en la alternativa perfecta para las constantes globales de oldschool. – Esko

18

En Groovy 1.8+, se puede lograr esto mediante el @Field annotation:

import groovy.transform.Field 

@Field final String MY_CONSTANT = 'constant' 

def printConstant() { println MY_CONSTANT } 

printConstant() 
+1

aunque no funciona desde el interior de una clase :( – Anentropic

+0

@Anentropic: no te pierdas la importación anterior "import groovy.transform.Field" – BTakacs

0

La otra manera eficaz de añadir la aplicación a escala mundial son constantes de nivel declarar una interfaz en el paquete adecuado como

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. 

} 

uso de constantes en cualquier clase como abajo,

import packageNameContainingInterface.applicationConstants // import statement. 
def adminUser = applicationConstants.ADMIN_USER 
println adminUser 
Cuestiones relacionadas