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
andcaller
refer to the same scope?
Thanks, Don
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.
"
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 onlyfoo()
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.owner: the enclosing object (this or a surrounding Closure).
Take a look at page 144
For your questions;
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.
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