1

ここには、類似しているが十分に異なる他の質問がいくつかあります。これを新しい質問として提起する必要があります。

空のクラスを作成しました。それを Test と呼びましょう。プロパティやメソッドはありません。次に、キーと値のペアのマップを反復処理し、キーにちなんで名付けられた値を含むプロパティを動的に作成します...次のように:

def langMap = [:]
langMap.put("Zero",0)
langMap.put("One",1)
langMap.put("Two",2)
langMap.put("Three",3)
langMap.put("Four",4)
langMap.put("Five",5)
langMap.put("Six",6)
langMap.put("Seven",7)
langMap.put("Eight",8)
langMap.put("Nine",9)

langMap.each { key,val ->
    Test.metaClass."${key}" = val
}

これで、次のように作成された新しいメソッドからこれらにアクセスできます。

Test.metaClass.twoPlusThree = { return Two + Three }
println test.twoPlusThree()

私がやりたいのは、「Two + Three」のような文字列から一連の命令を動的にロードし、その場でメソッドを作成して結果を評価し、式を含む多くの文字列に対してこのプロセスを繰り返し繰り返すことです。たまたま持っています。

質問: a) まず、これを行うためのより優れたエレガントな方法はありますか (私が提供した情報に基づいて) ? b) このパスが実行可能であると仮定すると、文字列がこのクラスのメソッド内でのみ有効な変数名を参照する場合、文字列からこのクロージャーを動的に構築する構文は何ですか?

ありがとう!

4

1 に答える 1

2

正解はあなたが実際に何をしようとしているのかによると思います。入力文字列を次のようなより複雑な式にすることはできます'(Two + Six) / Four'か?

より複雑な式を許可する場合は、文字列をGroovy式として直接評価することをお勧めします。GroovyConsoleまたはGroovyスクリプト内で、を直接呼び出すことができますevaluate。これにより、そのスクリプトのコンテキストで式が評価されます。

def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()

// Add each numer name as a property to the script.
numNames.eachWithIndex { name, i ->
    this[name] = i
}

println evaluate('(Two + Six) / Four') // -> 2

スクリプトに適した世界にいない場合は、次のGroovyShellクラスを使用できます。

def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
def langMap = [:]
numNames.eachWithIndex { name, i -> langMap[name] = i }

def shell = new GroovyShell(langMap as Binding)
println shell.evaluate('(Two + Six) / Four') // -> 2

ただし、evalを使用することは非常に危険であることに注意してください。入力文字列がユーザー生成である場合、この方法を使用することはお勧めしません。ユーザーは、のようなものを入力でき"rm -rf /".execute()、スクリプトの権限に応じて、そのスクリプトが実行される場所からすべてを消去できます。最初に、入力文字列が「安全」であることを検証できます(おそらく、既知の演算子、空白、括弧、および数字の名前のみが含まれていることを確認します)が、それが十分に安全かどうかはわかりません。

もう1つの方法は、これらの式に独自のミニ言語を定義し、ANTLRなどを使用してそれらを解析することです。しかし、繰り返しますが、これは本当にあなたが達成しようとしていることに依存します。

于 2012-07-15T01:34:07.943 に答える