开发者

Passing delegate through nested closures in Groovy

I am creating a builder which accepts Groovy closures as markup. However I am having trouble catching method calls with nested closures.

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()
    cl开发者_高级运维one.delegate = this
    clone()
  }
  def missingMethod (String name, args) {
     println "missing ${name} ${args}"
  }
}

Is there any way I can set the delegate property for nested closures?


If you want to write a builder, you should consider extending BuilderSupport instead of writing it all yourself from scratch. It takes care of delegating each method call to the correct object.

Here's an example of a JSON builder I wrote by extending this class.


i'd go with no, you cant. and you probably don't need it.
first. you are either the owner or the delegate of a closure. if you directly call a closure defined somewhere else, the call is resolved without your builder assistance.
second. do you really need that nested()? i believe you could easily use execute nested instead

here's an example of what i mean

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}"
  }
}

as a side note, i don't think builder support is the way to go. it might be useful for creating builders in java. but pure groovy is far easier. at least for small to medium complexity builders (never wrote a really large one).
you do need some knowledge of groovy's method dispatch process though

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜