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
"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.
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
{
def self = ({ owner })()
}
owner: the enclosing object (this or a surrounding Closure).
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.