Spesso si desidera dichiarare le costanti nella parte superiore di uno script che può essere referenziato in qualsiasi altro punto dello script. In Groovy, sembra che se dichiari una costante usando la finale, non è accessibile negli ambiti figlio. Qual è la soluzione per questo requisito molto basilare e comune? La soluzione che ho adesso è quella di creare una variabile non legata, ma questa non è una costante e non è elegante.Costanti globali in Groovy
risposta
Groovy non ha un ambito globale. Quando hai uno script groovy che non dichiara una classe, si impegna implicitamente in una classe con il nome dello script. Quindi le variabili finali a livello di alto livello sono in realtà solo campi della classe implicita. Per esempio:
// foo.groovy
final MYCONSTANT = "foobar"
println MYCONSTANT
class Helper {
def hello() { println MYCONSTANT } // won't work
}
new Helper().hello()
è più o meno 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
}
E 'facile capire il motivo per cui non funziona ampliato. Una soluzione semplice è dichiarare i tuoi "globali" in una classe fittizia chiamata per es. Costanti, quindi esegui solo un'importazione statica. Funziona anche tutto in un singolo script. Esempio:
import static Constants.*
class Constants {
static final MYCONSTANT = "foobar"
}
println MYCONSTANT
class Helper {
def hello() { println MYCONSTANT } // works!
}
new Helper().hello()
EDIT:
Inoltre, gli script sono po 'un caso speciale. Se dichiari una variabile senza def
o qualsiasi modificatore come final
, (per esempio, utilizzalo) entra in un'associazione a livello di script. Quindi in questo caso:
CONSTANT = "foobar"
println "foobar"
costante è nel livello di sceneggiatura vincolante, ma in:
final CONSTANT = "foobar"
println "foobar"
costante è una variabile locale nel metodo dello script run()
. Ulteriori informazioni su questo può essere trovato alla https://web-beta.archive.org/web/20150108090004/http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22
In Groovy 1.8+, è possibile raggiungere questo obiettivo con il @Field
annotation:
import groovy.transform.Field
@Field final String MY_CONSTANT = 'constant'
def printConstant() { println MY_CONSTANT }
printConstant()
non funziona all'interno di una classe però :( – Anentropic
@Anentropic: non perdere l'importazione sopra "import groovy.transform.Field" – BTakacs
L'altro modo efficace per aggiungere l'applicazione globale delle costanti di livello sono dichiarare uno un'interfaccia in pacchetto adatto come
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.
}
Utilizzo di costanti in qualsiasi classe come sotto,
import packageNameContainingInterface.applicationConstants // import statement.
def adminUser = applicationConstants.ADMIN_USER
println adminUser
Le costanti dovrebbero essere enumerazioni nel mondo Java 1.5+ ... :) – Esko
@Esko ogni tipo di costante dovrebbe essere un Enum? Anche qualcosa come GRAVITY o PI? O_o –
@tim_yates: No, un enum dovrebbe contenere tutte le costanti collegate tra loro. Nel tuo esempio potrebbe essere qualcosa come 'CelestialObjectAttributes.GRAVITY' o' MathematicConstants.PI'. Anche questi possono essere importati in modo da non dover ripetere il nome dell'enumerazione e le enumerazioni sono sempre VM (* o classloader *) globali che li rende l'alternativa perfetta per le costanti globali oldschool. – Esko