简体   繁体   English

通过 Groovy 中的嵌套闭包传递委托

[英]Passing delegate through nested closures in Groovy

I am creating a builder which accepts Groovy closures as markup.我正在创建一个接受 Groovy 闭包作为标记的构建器。 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()
    clone.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.如果你想编写一个构建器,你应该考虑扩展BuilderSupport而不是自己从头开始编写。 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. 这是我通过扩展此类编写的 JSON 构建器示例

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() ?你真的需要那个nested()吗? i believe you could easily use execute nested instead我相信您可以轻松地使用execute nested

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.它可能对在 Java 中创建构建器很有用。 but pure groovy is far easier.但纯粹的 groovy 要容易得多。 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你确实需要一些关于 groovy 的方法调度过程的知识

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM