web-dev-qa-db-ja.com

Groovyのグローバル定数

スクリプトのどこででも参照できるスクリプトの先頭で定数を宣言することがしばしば望まれます。 Groovyでは、finalを使用して定数を宣言すると、子スコープでアクセスできないようです。この非常に基本的で一般的な要件に対する解決策は何ですか?私が今持っている回避策は、バインドされていない変数を作成することですが、これは定数ではなく、エレガントではありません。

46
justGroovy

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

77
ataylor

Groovy 1.8以降では、 @Field注釈

import groovy.transform.Field

@Field final String MY_CONSTANT = 'constant'

def printConstant() { println MY_CONSTANT }

printConstant()
21
bmaupin

個人的にはしませんが、技術的にはできます

Object.metaclass.MYCONSTANT = 'foobar'

その後、すべてのオブジェクトがそれを持っています

0
Adam Taylor

グローバルアプリケーションレベルの定数を追加するもう1つの効率的な方法は、適切なパッケージで1つinterfaceを宣言することです。

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
0
Nitin Dhomse