заводное закрытие Expando вызов против явного

Если у меня есть закрытие, прикрепленное к расширению, и закрытие ссылается на значение в расширении, например...

def e = new Expando()
e.val = 'hi'
e.doit = { println delegate.val }
e.doit()

Это работает нормально. и печатает "привет"

Если я вызову закрытие с длинной формой

e.doit.call()​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

Выдает ошибку

groovy.lang.MissingPropertyException: No such property: val for class: Script1
at Script1$_run_closure1.doCall(Script1.groovy:4)
at Script1$_run_closure1.doCall(Script1.groovy)
at Script1.run(Script1.groovy:6)

Это происходит из-за того, что делегат меняется с e на script. Почему? Я думал, что e.doit() и e.doit.call() должны быть одинаковыми.

Я могу изменить делегата вручную - вот так

def e = new Expando()
e.val = 'hi'
e.doit = { println delegate.val }
e.doit.delegate=e;
e.doit.call()​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

Любые идеи о том, как пропустить явную настройку делегата?


person Joseph Collins    schedule 27.06.2013    source источник


Ответы (1)


Да, есть идея получше.

Обратитесь к экземпляру Expando напрямую (вместо делегата), когда вы знаете, что у вас есть закрытие (динамический метод), определенное для Expando, который является не чем иным, как динамическим компонентом. С другой стороны, тот же тест даст ожидаемый результат при тестировании на конкретном классе:

def e = new Expando()
e.val = 'hi'
e.doit = {
    println delegate.class.name
    "$e.val Joseph"
}

assert e.doit() == 'hi Joseph'
assert e.doit.call() == 'hi Joseph'

class Test{
    String a
    def printA = {
        println delegate.class.name
        "$delegate.a Joseph"
    }
}
def test = new Test(a: 'hi')

assert test.printA() == 'hi Joseph'
assert test.printA.call() == 'hi Joseph'

Обратите внимание на систему из println в обоих случаях.

person dmahapatro    schedule 28.06.2013