Loading...

April 27, 2011

Groovy Goodness: Tuple Constructor Creation

Groovy 1.8 adds the @TupleConstructor annotation. With this annotation we can automatically create a tuple constructor at compile time. So the constructor can be found in the compiled class. For each property in the class a parameter in the constructor is created with a default value. The order of the properties defined in the class also defines the order of parameters in the constructor. Because the parameters have default values we can use Groovy syntax and leave parameters at the end of the parameter list out when we use the constructor.

We can also include fields as constructor parameters. We use the annotation attribute includeFields=true to activate this.

If we define our constructors in the class than the TupleConstructor annotation will not create extra constructors. But we can override this behaviour with the attribute value force=true. We have to make sure we don't have constructor conflicts ourselves, because now the annotation will create the extra constructors.

If our class extends another class and we want to include the properties or fields of the super class we can use the attributes includeSuperProperties and includeSuperFields. We can even instruct the annotation to create code in the constructor to call the super constructor of the super class with the properties. We must set the annotation attribute callSuper=true to make this happen.

import groovy.transform.TupleConstructor

@TupleConstructor()
class Person {
    String name
    List likes
    private boolean active = false
}

def person = new Person('mrhaki', ['Groovy', 'Java'])

assert person.name == 'mrhaki'
assert person.likes == ['Groovy', 'Java']

person = new Person('mrhaki')

assert person.name == 'mrhaki'
assert !person.likes
// includeFields in the constructor creation.
import groovy.transform.TupleConstructor

@TupleConstructor(includeFields=true)
class Person {
    String name
    List likes
    private boolean active = false

    boolean isActivated() { active }
}

def person = new Person('mrhaki', ['Groovy', 'Java'], true)

assert person.name == 'mrhaki'
assert person.likes == ['Groovy', 'Java']
assert person.activated
// use force attribute to force creation of constructor
// even if we define our own constructors.
import groovy.transform.TupleConstructor

@TupleConstructor(force=true)
class Person {
    String name
    List likes
    private boolean active = false

    Person(boolean active) {
        this.active = active
    }

    boolean isActivated() { active }
}

def person = new Person('mrhaki', ['Groovy', 'Java'])

assert person.name == 'mrhaki'
assert person.likes == ['Groovy', 'Java']
assert !person.activated

person = new Person(true)

assert person.activated
// include properties and fields from super class.
import groovy.transform.TupleConstructor

@TupleConstructor(includeFields=true)
class Person {
    String name
    List likes
    private boolean active = false

    boolean isActivated() { active }
}

@TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)
class Student extends Person {
    List courses
}

def student = new Student('mrhaki', ['Groovy', 'Java'], true, ['IT'])

assert student.name == 'mrhaki'
assert student.likes == ['Groovy', 'Java']
assert student.activated
assert student.courses == ['IT']