Закрытие с делегатом, который не является groovy -объектом (например, происходит из обычной java -библиотеки), никогда не вызовет объект 'methodMissing', добавленный к этому делегату с использованием его метакласса, если вызов сделал 'неявным' (т.е. не вызывая его явно для 'делегата' в замыкании).
Приведенный ниже код делает явный и неявный вызов несуществующего метода; это делается для экземпляра класса Groovy, объекта GString и объекта, отличного от groovy. Единственный сбой - это неявный вызов не groovy -объекта (т.е. c. ArrayList).
(Вы можете увидеть и запустить тот же код онлайн: https://groovyconsole.appspot.com/edit/5200829376102400)
Не уверен, является ли это ошибкой или ограничением - ссылки на methodMissing, определенные через metaClass, довольно редки. Любые проницательные комментарии приветствуются.
class ClosureDelegate {
def testMissingMethod(def someObject) {
someObject.metaClass.methodMissing = { String name, args ->
println name
}
def closure = {
delegate.anything()
anything() // this one fails on non-groovyclasses
}
closure.delegate = someObject
closure.resolveStrategy = Closure.DELEGATE_ONLY
closure()
}
}
class TestObject {}
println "testing with TestObject"
new ClosureDelegate().testMissingMethod(new TestObject())
println "testing with GString"
new ClosureDelegate().testMissingMethod("${new Date()}")
println "testing with ArrayList"
new ClosureDelegate().testMissingMethod(new ArrayList())
testing with TestObject
anything
anything
testing with GString
anything
anything
testing with ArrayList
anything
Caught: groovy.lang.MissingMethodException: No signature of method: ClosureDelegate$_testMissingMethod_closure2.anything() is applicable for argument types: () values: []
Possible solutions: toString(), toString(), any(), any()