Domanda

If I have a closure attached to an expando and the closure references a value on the expando like so...

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

It works fine. and prints 'hi'

If I call the closure with the long form

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

It throws an error

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)

This happens because the delegate is changed from e to the script. Why? I thought that e.doit() and e.doit.call() are supposed to be the same.

I can change the delegate manually - like so

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

Any ideas on how to skip the explicit setting of the delegate?

È stato utile?

Soluzione

Yes, there is a better idea.

Refer Expando instance directly (instead of delegate) when you know you are having a closure(dynamic method) defined for the Expando which is nothing but a dynamic bean. On the other hand, the same test would yield expected result when tested against a concrete class:

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'

Note system out from println in both cases.

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