2

Groovyクロージャをマークアップとして受け入れるビルダーを作成しています。ただし、ネストされたクロージャを使用してメソッド呼び出しをキャッチするのに問題があります。

Closure nested = {
   foo ()       //will throw missingMethod exception
}
Closure root = {
   foo ()       //prints 'missing foo []'
   inline_nested {
     foo ()     //prints 'missing foo []'
   }
   nested ()    
}
builder.execute (root)

// ...
class MyBuilder {
  void execute (Closure closure) {
    def clone = closure.clone()
    clone.delegate = this
    clone()
  }
  def missingMethod (String name, args) {
     println "missing ${name} ${args}"
  }
}

ネストされたクロージャのデリゲートプロパティを設定する方法はありますか?

4

2 に答える 2

2

ビルダーを作成する場合は、すべてを最初から作成するのではなく、BuilderSupportを拡張することを検討する必要があります。各メソッド呼び出しを正しいオブジェクトに委任します。

これは、このクラスを拡張して作成したJSONビルダーの例です。

于 2011-05-12T08:48:49.933 に答える
1

私はノーで行きます、あなたはできません。そして、あなたはおそらくそれを必要としないでしょう。
最初。あなたはクロージャの所有者または代理人のいずれかです。別の場所で定義されたクロージャを直接呼び出す場合、その呼び出しはビルダーの支援なしで解決されます。
2番目。本当に必要ですnested()か?execute nested代わりに簡単に使用できると思います

これが私の意味の例です

def nested2 = {
  someMethodAtNested2 '3'
  println "nested2! - $it"
}
def nested1 = {arg1,arg2->
  someMethodAtNested1 '2'
  println "nested1! - $arg1"
  include nested2, arg2
}
def root = {
  someMethodAtRoot '1'
  println "root!"
  include nested1, 'param1', 'param2'
}
new FooBuilder().build root

class FooBuilder {
  void build(Closure closure) {
    include closure
  }
  def include(Closure closure, ...args) {
    def clone = closure.clone()
    clone.delegate = this
    clone.resolveStrategy = Closure.DELEGATE_FIRST
    clone(*args)
  }
  def methodMissing(String name, args) {
    println "missing ${name} ${args}"
  }
}

ちなみに、ビルダーのサポートは道ではないと思います。Javaでビルダーを作成するのに役立つかもしれません。しかし、純粋なグルーヴィーははるかに簡単です。少なくとも中小規模の複雑なビルダーの場合(本当に大きなものを書いたことはありません)。
ただし、groovyのメソッドディスパッチプロセスに関する知識は必要です。

于 2011-05-14T00:15:11.207 に答える