Alexandr
Alexandr

Reputation: 9525

Owners in groovy closures

According to "Groovy in Action", closures can be declared via several ways. A couple of ways: def printer = { line -> println line } def Closure getPrinter() { return { line -> println line } }

According to Closures, official documentation owner in closure

"return the direct enclosing object, be it a closure or a class."

Ok, let's have a look at:

class Mother {
    def prop = 'prop'
    def method(){ 'method' }
    Closure birth (param) {
        def local = 'local'
        def closure1 = {
            [ this, prop, method(), local, param ]
        }
        return closure1
    }

    def birth2 = { param ->
        def local = 'local'
        def closure2 = {
            [ this, prop, method(), local, param ]
        }
        return closure2
    }
}
Mother julia = new Mother()
def closure = julia.birth('param')
assert closure.owner == julia
assert closure.delegate == julia

def closure2 = julia.birth2('param')
assert closure2.owner == julia  
assert closure2.delegate == julia

In both cases, birth anb birth2 are closures according to documentation. Inside these closures we declare closure1 and closure2. I gave them names just to refer to them. The owners of these closure1 and closure2 should refer to birth and birth2. According to the official documentation. But in first example owner refers to instance of class - julia. In the second example, I believe it refers to birth2, but don't know how to assert it.

Can anyone explain the difference, please?

Upvotes: 1

Views: 489

Answers (2)

Catalin
Catalin

Reputation: 484

You get already the explanation regarding the difference between birth and birth2, one is a method and the other is a closure. However, both return a Closure object and the question about how to assert the owner and the delegate is still not answered. Here it is:

class Mother {
    def prop = 'prop'
    def method(){ 'method' }
    Closure birth (param) {
        def local = 'local'
        def closure1 = {
            [ this, prop, method(), local, param ]
        }
        return closure1
    }

    def birth2 = { param ->
        def local = 'local'
        def closure2 = {
            [ this, prop, method(), local, param ]
        }
        return closure2
    }
}
Mother julia = new Mother()
def closure = julia.birth('param')
assert closure.owner == julia
assert closure.delegate == julia

def closure2 = julia.birth2('param')
assert closure2.owner ==  julia.birth2
assert closure2.delegate == julia.birth2

You are of course right, owner and delegate of closure2 are birth2. The owner of the closure2 is the next object which holds it, which by definition is either an class or another closure. Note that the owner cannot be another method as we see in case of closure1.

The delegate of the closure is the context where that delegate solves it's names which by default is the owner. In our case the delegate of the closure2 is birth2. The context of birth2 where the names are solved is again it's owner by default which is the class Mother, that is why prop and method() are known in closure2.

However, groovy has a cool feature that allows you to change the context where a closure is evaluated, so you could call closure2 for a completely unrelated object exposing the same names as Mother. This is possible by changing the delegate and either accessing the properties with delegate.property or by just changing the implicit delegation strategy. See delegate of a closure.

Here is a small example how to use it:

class Person {
    String name
    int age
    def describe = { "$name is $age years old." }
}
person = new Person(name: 'John', age: 42)
assert person.describe() == "John is 42 years old."

closure = person.describe
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.delegate = [name: 'Mike', age:'66']
assert closure() == "Mike is 66 years old."

Upvotes: 0

tim_yates
tim_yates

Reputation: 171144

birth is a method, not a closure

birth2 is a closure

Therein lies the difference

Upvotes: 0

Related Questions