Groovy: meaning of 'this' inside a closure

2019-03-25 15:26发布

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

4条回答
ら.Afraid
2楼-- · 2019-03-25 16:02

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.

查看更多
来,给爷笑一个
3楼-- · 2019-03-25 16:09

"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.

查看更多
淡お忘
4楼-- · 2019-03-25 16:17
{
    def self = ({ owner })()
}

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

查看更多
SAY GOODBYE
5楼-- · 2019-03-25 16:22

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

查看更多
登录 后发表回答