Groovy: meaning of 'this' inside a closure

14,037

Solution 1

"this" in a block mean in Groovy always (be it a normal Java-like block or a Closure) the surrounding class (instance). "owner" is a property of the Closure and points to the embedding object, which is either a class (instance), and then then same as "this", or another Closure. I would forget about the scope thing totally for this part. So in the case above it is correct, that "this" refers to a mother.

And now to make things complicated... "this" and the implicit this are not the same in Groovy. So if you have a Closure {foo()} and {this.foo()} you can get differing results. this.foo() will always be resolved to the embedding class, while only foo() will be resolved using the Groovy meta object protocol (MOP) and can point to something entirely different. A builder may for example set a delegate on that Closure and catch the method invocation, for a Groovy builder that is standard. Anyway... that is why this part is called dynamic scoping.

Historic background: Before Groovy 1.0 "this" was the Closure object itself. But was changed because actually calling this.foo() became impossible if a builder did capture all calls. then you had no way to call local methods from within the builder anymore. There was a lot of tries with changing the standard resolve strategy - and big emotional discussions too. But in the end, changing "this" to refer to the embedding class was a simple solution to the problem and is more in line with people coming from Java plus it let's you easily bypass the MOP if you insist.

Solution 2

Take a look at page 144

...this refers to the closure, not to the declaring object. At this point, closures play a trick for us. They delegate all method calls to a so-called delegate object, which by default happends to be the declaring object (that is, the owner). This make the closure appear as if the enclosed code runs in the birthday context.

For your questions;

this inside a closure evaluates to the scope in which the closure is called?

from the book they state that "this refer to the closure, not to the declaring object" But from bertport and my experiment, it seems "this" is actually the declaring object.

Either ways, the answer is still "no" for your question.

within the closure shown above, this and caller refer to the same scope?

I'm afraid not.

Be aware that page 143 and 144 in Groovy in Action need some corrections

http://groovy.canoo.com/errata/erratum/show/5

http://groovy.canoo.com/errata/erratum/show/8

Solution 3

{
    def self = ({ owner })()
}

owner: the enclosing object (this or a surrounding Closure).

Solution 4

Sake says, "this is the closure not the object where the closure [is] constructed." But when we run this script, we find that this is a Mother, not a Closure.

Share:
14,037
Dónal
Author by

Dónal

I earn a living by editing text files. I can be contacted at: [email protected] You can find out about all the different kinds of text files I've edited at: My StackOverflow Careers profile

Updated on June 03, 2022

Comments

  • Dónal
    Dónal about 2 years

    The following example is adapted from 'Groovy in Action'

    class Mother {
    
        Closure birth() {                            
            def closure = { caller ->
                [this, caller]
            }
            return closure
        }
    }                    
    
    Mother julia = new Mother()
    closure = julia.birth()                                
    context = closure.call(this)                             
    
    println context[0].class.name        // Will print the name of the Script class
    assert context[1] instanceof Script 
    

    According to the book, the value of this inside the closure is the outermost scope (i.e. the scope in which julia is declared). Am I right in assuming that

    • this inside a closure evaluates to the scope in which the closure is called?
    • within the closure shown above, this and caller refer to the same scope?

    Thanks, Don

  • Sake
    Sake about 13 years
    Yeah. You are right context[0] is indeed the Mother(julia). The book didn't explain it correctly.
  • Luis Muñiz
    Luis Muñiz over 7 years
    Thanks @blackdrag for the explanation! So am I right in saying that while executing a closure, it is impossible to get a reference to the Closure itself?
  • blackdrag
    blackdrag over 7 years
    ´def cl; cl = {return cl}; assert cl() == cl´ shows how you can get hold of a reference to be used inside the block. But it is right, that it is impossible to get a reference to the Closure without using the outside context.