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:
...
| Code Block |
|---|
def counter= [:]
try{
def count= 0
counter.incr= { count++; counter.show() }
counter.decr= { count--; counter.show() }
counter.show= { count }
}
counter.incr()
assert counter.show() == 1
|
Expando
We can access private variables with an Expando instead. An expando allows us to assign closures to Expando names:
...
There is a better way to ensure a chosen variable name will not "shadow" another from the same scope.
Static Classes
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:
...
| Code Block |
|---|
class Counter{
static count = 0
static{ println 'Counter first accessed' } //static initializer
static incr( n ){ count += n }
static decr( n ){ count -= n }
}
println 'incrementing...'
Counter.incr(7) //'Counter first accessed' printed here
println 'decrementing...'
Counter.decr(4) //nothing printed
|
Instantiable Classes
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:
...
| Code Block |
|---|
class A{
def list= []
A(){
list<< "A constructed"
}
A(int i){
this()
//a constructor can call another constructor if it's the first statement
list<< "A constructed with $i"
}
A(String s){
this(5)
list<< "A constructed with '$s'"
}
}
def a1= new A()
assert a1.list == ["A constructed"]
def a2= new A(7)
assert a2.list.collect{it as String} == [
"A constructed",
"A constructed with 7",
]
def a3= new A('bird')
assert a3.list.collect{it as String} == [
"A constructed",
"A constructed with 5",
"A constructed with 'bird'",
]
|
Categories
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:
...