Preface:
Java has two basic informal rules for scoping:
Java does know classwide variables and local variables. Local variables are defined as method parameter or inside the method block. Classwide variables are defined as attributes of the class. Of course Java does violate this first principle I showed at top here a little since I can access class wide variables from outside the class, if the access modifier is for example public. A local variable of the same name as an attribute does not violate the second principle, as the attribute is hidden by the local variable and with this no longer visible without using a qualifier like "this".
Now, what about Groovy?
In Groovy we also have these two principles, but since we have different constructs, we may lay out these principles in a different way. Let us start with local variables.
So what is different? When you define a variable in a script it is always local. But methods are not part of that scope. So defining a method using different variables as if they were attributes and then defining these variables normally in the script leads to problems. Example:
- Example of disallowed definition in scripts
- String attribute = "bar"
- void aMethod(){
- assert attribute == "bar" // Not allowed !
- }
- aMethod()
The only things the method has access to are:
When is something in the Binding and when not?
That's easy. When it is not defined, it is in the binding. The trick is - and that is admittedly not easy for Java programers - to not to define the variable before using it, and it will go into the binding. Any defined variable is local. Please note: the binding exists only for scripts.
- Example of binding variable in scripts
- attribute = "bar" //Binding variable
- void aMethod(){
- assert attribute == "bar" // Not allowed !
- }
- aMethod()
What is this "def" I heard of?
"def" is a replacement for a type name. In variable definitions it is used to indicate that you don't care about the type. In variable definitions it is mandatory to either provide a type name explicitly or to use "def" in replacement. This is needed to the make variable definitions detectable for the Groovy parser. You can think of "def" as an alias of "Object" and you will understand it in an instant.
These definitions may occur for local variables in a script or for local variables and properties/fields in a class. "def" can also replace "void" as the return type in a method definiton. Below example show how "def" can be assigned to different class Object:
- def dynamic = 1
- dynamic = "I am a String stored in a variable of dynamic type"
- int typed = 2
- typed = "I am a String stored in a variable of type int??" // throws ClassCastException
A Closure is a block:
In the terms of the principles above a closure is a block. A variable defined in a block is visible in that block and all blocks that are defined in that block. For example in Java:
- a java code
- {
- int i=1;
- {
- System.out.println (i);
- }
- }
In Groovy we have an additonal structure with "{", the closure. To follow the principles above, it is not allowed to define two variables of the same name in a closure.
- Not allowed
- def closure = { int i; int i }
- Invalid double definition of variables
- def outer = {
- int i
- def inner = { int i }
- }
- Allowed
- def closure1 = { parameter ->
- println parameter
- }
- def closure2 = { parameter ->
- println parameter
- }
And "it"?
"it" is a special variable name, that is defined automatically inside a closure. It refers always to the first parameter of the closure, or null, if the closure doesn't have any parameters. When using nested cosures (closures in closures) the meaning of "it" depends on the closure you are in.
- implicit it in closures
- def c = { it }
- assert c() == null
- assert c(1) == 1
- def outer = {
- def inner = { it+1 }
- inner(it+1)
- }
- assert outer(1) == 3
"static" is a modifier for attributes (and methods, but this is not at issue here). It defines the "static scope". That means all variables not defined with "static" are not part of that static scope and as such not visible there. There is no special magic to this in Groovy. So for an explanation of "static" use any Java book.
沒有留言:
張貼留言