Я хотел бы создать DSL с синтаксисом:Как передать методMissing вызовы вложенных классов?
Graph.make {
foo {
bar()
definedMethod1() // isn't missing!
}
baz()
}
Где, когда обработчик для этого дерева встречает крайнее закрытие, он создает экземпляр некоторого класса, который имеет некоторые определенные методы, а также его собственное обработчик отсутствующих методов.
Я полагал, что это будет достаточно легко с некоторой структурой, как:
public class Graph {
def static make(Closure c){
Graph g = new Graph()
c.delegate = g
c()
}
def methodMissing(String name, args){
println "outer " + name
ObjImpl obj = new ObjImpl(type: name)
if(args.length > 0 && args[0] instanceof Closure){
Closure closure = args[0]
closure.delegate = obj
closure()
}
}
class ObjImpl {
String type
def methodMissing(String name, args){
println "inner " + name
}
def definedMethod1(){
println "exec'd known method"
}
}
}
Но обработчик methodMissing интерпретирует все замыкание внутри Graph, а не делегируя внутреннее замыкание на ObjImpl, дающую выход:
outer foo
outer bar
exec'd known method
outer baz
Как я могу охватить отсутствующий вызов метода для внутреннего закрытия для внутреннего объекта, который я создаю?
Ах! Интересно. Таким образом, это похоже на проблему с охватом и может быть преодолено путем использования ключевого слова «this». В частности, вызов метода this.calculateSomething() 'разрешит этот метод. Преимущество, заключающееся в том, что он не держится вокруг стека, заключается в том, что код для устранения недостающих методов в> 2 вложенных замыканиях может храниться в соответствующем контексте (и я ожидаю, что он будет на 3-4 уровня) –
Правда, но поскольку большинство владельцев DSL работают сначала принцип наименьшего удивления предполагает, что вам не нужно этого делать. Я добавил альтернативный ответ, используя Groovy 'BuilderSupport', который может работать лучше для вас. –
Спасибо, я ценю альтернативные подходы. После некоторых экспериментов я по-прежнему предпочитаю делегировать поведение вложенных замыканий на вложенный объект. Хотя он отличается от стандартного Groovy DSL impl, он, как представляется, обеспечивает лучшее разделение проблем, и, учитывая мой стиль и предпочтительный стиль моих коллег, я думаю, что в конечном итоге DSL мы будем работать над более ремонтопригодными (и это важно). Я перерабатываю реализацию, в которой в настоящее время используется BuilderSupport, что, на мой взгляд, сложно выполнить. Тем не менее, я поддержал ваши ответы за ваши усилия и помощь. Благодаря! –