Передача делегата через вложенные замыкания в Groovy - PullRequest
2 голосов
/ 12 мая 2011

Я создаю конструктор, который принимает закрытия 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}"
  }
}

Можно ли как-то установить свойство делегата для вложенных замыканий?

Ответы [ 2 ]

2 голосов
/ 12 мая 2011

Если вы хотите написать конструктор, вам следует рассмотреть возможность расширения BuilderSupport вместо того, чтобы писать все самостоятельно с нуля.Он заботится о делегировании каждого вызова метода правильному объекту.

Вот пример построителя JSON, который я написал , расширяя этот класс.

1 голос
/ 14 мая 2011

Я бы пошел с нет, ты не можешь.и вам, вероятно, это не нужно.
сначала.Вы являетесь владельцем или делегатом закрытия.если вы напрямую вызываете замыкание, определенное где-то еще, вызов разрешается без вашей помощи строителя.
секунда.тебе действительно нужно это 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, хотя

...