I'm learning Groovy now and I bumped into something that I don't understand and I hope you'd be able to shed some light.
In regard to the following example:
import groovy.transform.Field
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
I understand that this anchoring allows me to change the scope of the awe variable from being run at the method level of the script to the class level of the script.
But then I think about the difference between defining a variables with def or without, example:
def var = "foo"
and
var = "foo"
As far as I understand the difference between the two examples is a difference of scope. When I assign a value to a variable without a "def" or other type, in a Groovy script, it's added to the "binding", the global variables for the script. Which means it can be accessed from all functions within the script.
So taking into consideration both "@Field" and defining a variable without using "def" and following that line of thought I've changed the example code to this:
import groovy.transform.Field
awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
And it works.
So my question is why use anchoring? if you can achieve the same goal by defining a variable without the "def"?
You do not achieve the same goal - see the difference below
import groovy.transform.Field
awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1
work fine as the variable is dynamically typed. On contrary this fails
import groovy.transform.Field
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1
As the variable is strong typed (java.util.ArrayList)
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
at FieldTest1.run(FieldTest1.groovy:5)
@Field is younger than scripts and the intended use is to give open blocks the ability to have additional state. If you are happy with the binding there is not really a big reason for doing it different. If you need the values in the binding of course, then @Field is no alternative. On the other hand, if the binding must contain only certain variables, then @Field can become a must
Example for intended usage:
def cl = {
Field x = 1
x++
}
In this example the open block cl would have a field x, the script would not have x in the binding, nor is there a local variable x. But the assignment x=1 is done only once when the open block is created. But you can still change the value by operations on that field. That way each call cl() will produce a new value, starting with 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With