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

发布于 2024-11-06 10:56:45 字数 578 浏览 5 评论 0原文

我正在创建一个接受 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}"
  }
}

有什么方法可以设置嵌套闭包的委托属性吗?

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()
    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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沧笙踏歌 2024-11-13 10:56:45

如果你想编写一个构建器,你应该考虑扩展 BuilderSupport 而不是自己从头开始编写。它负责将每个方法调用委托给正确的对象。

这是我编写的 JSON 构建器的示例扩展这个类。

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.

陌若浮生 2024-11-13 10:56:45

我会选择不,你不能。你可能不需要它。
第一的。您是闭包的所有者或代表。如果您直接调用其他地方定义的闭包,则无需构建器的帮助即可解决该调用。
第二。你真的需要那个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 方法调度过程的知识

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文