Accessing Private Variables
Closures and functions can't remember any information defined within themselves between invocations. If we want a closure to remember a variable between invocations, one only it has access to, we can nest the definitions inside a block:
We can have more than one closure accessing this private variable:
We can also put all closures accessing common private variables in a map to show they're related:
We can access private variables with an Expando instead. An expando allows us to assign closures to Expando names:
An expando can also be used when common private variables aren't used:
Like individual closures, closures in expandos see all external variables all the way to the outermost block. This is not always helpful for large programs as it can limit our choice of names:
For single-argument closures, both standalone and within expandos, we can use the implicit parameter as a map for all variables to ensure they're all valid, though the syntax is not very elegant:
There is a better way to ensure a chosen variable name will not "shadow" another from the same scope.
Just as we can use functions instead of closures to hide names from the surrounding context, so also we can use static classes instead of expandos to hide such external names. We use the static keyword to qualify the individual definitions in a class definition:
Methods act quite similar to standalone functions. They can take parameters:
We can have more than one method of the same name if they each have different numbers of parameters.
Methods are also similar to other aspects of functions:
We can assign each method of a static class to a variable and access it directly similar to how we can with functions:
When there's no accessibility keyword like 'public' or 'private' in front of a field within a static class, it becomes a property, meaning two extra methods are created:
When we access the property value using normal syntax, the 'getter' or 'setter' is also called:
To run some code, called a static initializer, the first time the static class is accessed. We can have more than one static initializer in a class.
We can write instantiable classes, templates from which we can construct many instances, called objects or class instances. We don't use the static keyword before the definitions within the class:
We can run some code the first time each object instance is constructed. First, the instance initializer/s are run. Next run is the constructor with the same number of arguments as in the calling code.
If we don't define any constructors, we can pass values directly to fields within a class by adding them to the constructor call:
Methods, properties, and fields on instantiable classes act similarly to those on static classes:
A class can have both static and instantiable parts by using the static keyword on the definitions that are static and not using it on those that are instantiable:
A class can have more than one constructor:
When a class has a category method, that is, a static method where the first parameter acts like an instance of the class, we can use an alternative 'category' syntax to call that method:
We can also use category syntax when the category method/s are in a different class:
Many supplied library classes in Groovy have category methods that can be called using category syntax. (However, most category methods on Numbers, Characters, and Booleans do not work with category syntax in Groovy-1.0)
Far more common are supplied library classes having category methods in another utility class, eg, List having utilities in Collections:
We can call category methods inside other category methods:
But we can't call category methods inside another category method from the same class:
A lot of entities in Groovy are classes, not just the explicit ones we've just learnt about. Numbers, lists, sets, maps, strings, patterns, scripts, closures, functions, and expandos are all implemented under the hood as classes. Classes are the building block of Groovy.