Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
Chapter 5

[ 107 ]

myClazz.member = "second"
def clos2 = myClazz.method("second")
then: "new member, local and parameter values are bound"
clos2() == "Member: second Local: second Parameter: second"
and: "but the first still has the old parameter and locals bound"
clos1() == "Member: second Local: first Parameter: first"

Here we are examining the effect on scoped variables when we make multiple calls
to a method that returns a closure. To keep things simple in this example, we are not
modifying any variables within the closure. The first time that we call method, we
return a closure which, when invoked, outputs the following:


Member: first Local: first Parameter: first

Both the field member and local variable reflect the first state of the member field
because the local variable is just a copy of the field variable. The parameter variable
reflects the parameter value that we just passed to method.


Before calling the method for a second time, we can change the member variable to
second. When we invoke the closure that is returned from this call, we see:


Member: second Local: second Parameter: second

The field member and local variable reflect the second state of the member field,
and the parameter value is what we just passed to the method. We then call the first
closure for a second time, and we see:


Member: second Local: first Parameter: first

The member field shows the latest state of the field member, but the local variable
and parameter are preserved in the same state as when the first call to method was
made. If we had modified one or more local variables, then eventually all bets will
be off in terms of the state of these variables in relation to any particular closure
instance. I recommend caution whenever returning closures from methods. Ensure
that you fully understand the impact of the variables that you are acting upon and
the state they will have when called is truly the state that you expect.


This note of caution also extends to accessing field members from a returned closure.
While we can at least be sure that the state of a field member is the same whether it is
accessed from the class or the closure, there is also the impact on the encapsulation of
the class to be considered. When we pass a closure back from a class method, we are
potentially giving insecure access to the inner workings of the class.

Free download pdf