Search

Dark theme | Light theme

October 13, 2016

Groovy Goodness: Direct Field Access In (Super) Classes

When we use the property syntax of Groovy to get the value for a property, Groovy will actually try to invoke a get method for that property if it is available. So for example if we have the statement user.name actually user.getName() is invoked. If we want to reference a property field directly, so bypassing the get method, we must place an @ in front of the property field name. In the previous example we would write user.@name to get the field value directly. The same rules apply for setting a value for a property with the Groovy syntax. If we write user.name = 'mrhaki' then actually user.setName('mrhaki') is invoked. We can use the @ prefix also to set a value without invoking the set method for that property. So in our example it would be user.@name = 'mrhaki' and the setName method is not used.

In the following example we have a class Person with a name property. We add a getName method which formats the name field and returns the value. In a subclass User we access the name property from the super class using the Groovy property syntax and with the @ prefix:

class Person {
    // We must not leave out a modifier,
    // because without a modifier, 
    // Groovy would add
    // a getName and setName method if
    // they are not already available.
    // But Groovy also adds a private modifier
    // for this property and being
    // private it is not accessible from
    // subclasses.
    protected String name

    String getName() {
        "_${name}_"
    }

    void setName(String name) {
        this.name = "*${name}*"
    }
}

class User extends Person {
    String getUsername() {
        // .name will invoke getName().
        "User(${this.name})"
    }

    String getUsernameField() {
        // .@name will access name field.
        "User(${this.@name})"
    }
}

def u = new User(name: 'mrhaki')

assert u.username == 'User(_*mrhaki*_)'
assert u.usernameField == 'User(*mrhaki*)'
assert u.name == '_*mrhaki*_'
assert u.@name == '*mrhaki*'

// Set field value directly
u.@name = 'mrhaki'

assert u.username == 'User(_mrhaki_)'
assert u.usernameField == 'User(mrhaki)'
assert u.name == '_mrhaki_'
assert u.@name == 'mrhaki'

Written with Groovy 2.4.7.