Groovy: what's the purpose of "def" in "def x = 0"?

It's syntactic sugar for basic scripts. Omitting the "def" keyword puts the variable in the bindings for the current script and groovy treats it (mostly) like a globally scoped variable:

x = 1
assert x == 1
assert this.binding.getVariable("x") == 1

Using the def keyword instead does not put the variable in the scripts bindings:

def y = 2

assert y == 2

try {
    this.binding.getVariable("y") 
} catch (groovy.lang.MissingPropertyException e) {
    println "error caught"
} 

Prints: "error caught"

Using the def keyword in larger programs is important as it helps define the scope in which the variable can be found and can help preserve encapsulation.

If you define a method in your script, it won't have access to the variables that are created with "def" in the body of the main script as they aren't in scope:

 x = 1
 def y = 2


public bar() {
    assert x == 1

    try {
        assert y == 2
    } catch (groovy.lang.MissingPropertyException e) {
        println "error caught"
    }
}

bar()

prints "error caught"

The "y" variable isn't in scope inside the function. "x" is in scope as groovy will check the bindings of the current script for the variable. As I said earlier, this is simply syntactic sugar to make quick and dirty scripts quicker to type out (often one liners).

Good practice in larger scripts is to always use the "def" keyword so you don't run into strange scoping issues or interfere with variables you don't intend to.


Ted's answer is excellent for scripts; Ben's answer is standard for classes.

As Ben says, think of it as "Object" -- but it is much cooler in that it does not constrain you to the Object methods. This has neat implications with respect to imports.

e.g. In this snippet I have to import FileChannel

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*

import java.nio.channels.*

class Foo {
    public void bar() {
        FileChannel channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

e.g. But here I can just 'wing it' as long as everything is on the classpath

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
class Foo {
    public void bar() {
        def channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

According to this page, def is a replacement for a type name and can simply be thought of as an alias for Object (i.e. signifying that you don't care about the type).

Tags:

Groovy

Keyword