Domanda

Sto creando un costruttore che accetta chiusure groovy come markup. Tuttavia ho difficoltà a catturare le chiamate del metodo con chiusure nidificate.

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

Esiste un modo per impostare la proprietà delegata per le chiusure nidificate?

È stato utile?

Soluzione

Andrei con no, non puoi. E probabilmente non ne hai bisogno.
primo. Sei il proprietario o il delegato di una chiusura. Se si chiama direttamente una chiusura definita da qualche altra parte, la chiamata viene risolta senza l'assistenza al costruttore.
secondo. ne hai davvero bisogno nested()? Credo che potresti facilmente usare execute nested invece

Ecco un esempio di ciò che intendo

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

Come nota a margine, non credo che il supporto del costruttore sia la strada da percorrere. Potrebbe essere utile per creare costruttori in Java. Ma puro groovy è molto più facile. Almeno per i costruttori di complessità di piccole e media complessità (non ne ha mai scritto uno molto grande).
Tuttavia, hai bisogno di una certa conoscenza del processo di spedizione del metodo di Groovy

Altri suggerimenti

Se vuoi scrivere un costruttore, dovresti prendere in considerazione l'estensione Buildersupport Invece di scrivere tutto da solo da zero. Si occupa di delegare ogni chiamata al metodo all'oggetto corretto.

Ecco un esempio di un costruttore JSON che ho scritto estendendo questa classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top