Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Groovy Goodness: Using Package Scoped Methods, Fields and Classes

DZone's Guide to

Groovy Goodness: Using Package Scoped Methods, Fields and Classes

· Java Zone ·
Free Resource

Verify, standardize, and correct the Big 4 + more– name, email, phone and global addresses – try our Data Quality APIs now at Melissa Developer Portal!

Groovy uses the Java package protected scope visibility rules to turn methods and classes into public scoped variants and fields into properties. In Java package scope visibility is applied to any field, method or class that has no explicit scope set, like publicprotected or private. To get the same scope in Groovy we must use the AST transformation @PackageScope to explicitly define a field, method or class to have package scope.

In the following code we want to define a simple User class with an accessor method to change the username property. Only classes in the same package as the User class must be allowed to use this method. The method may not be invoked by classes in other packages or subclasses.

package com.mrhaki.groovy.domain

import groovy.transform.*

class User {
    private String username
    
    User(final String username) {
        this.username = username
    }

    @PackageScope 
    void changeUsername(final String newUsername) {
        this.username = newUsername
    }

    String getUsername() {
        username
    }
}

If we create a new class in another package and we want to invoke the method changeUsername() we get an error if we use @CompileStatic. We can also write a Java class to use our Groovy User class and then the compiler will also give an error.

// File: App.groovy
package com.mrhaki.groovy.app

import groovy.transform.*
import com.mrhaki.groovy.domain.User

@CompileStatic
def changeUsername() {
    final User user = new User('mrhaki')
    user.changeUsername 'Hubert A. Klein Ikkink'
}

changeUsername()

If we run the script with Groovy we get an IllegalAccessError:

$ groovyc User.groovy
$ groovy App.groovy
Caught: java.lang.IllegalAccessError: tried to access method com.mrhaki.groovy.domain.User.changeUsername(Ljava/lang/String;)V from class com.mrhaki.groovy.app.App
java.lang.IllegalAccessError: tried to access method com.mrhaki.groovy.domain.User.changeUsername(Ljava/lang/String;)V from class com.mrhaki.groovy.app.App
at com.mrhaki.groovy.app.App.changeUser(App.groovy:10)
at com.mrhaki.groovy.app.App.run(App.groovy:13)

If we write a Java class to invoke the package scoped method we get an error when we compile the class:

package com.mrhaki.groovy.app;

import com.mrhaki.groovy.domain.User;

public class Application {
    public static void main(final String[] args) {
        final User user = new User("mrhaki");
        user.changeUsername("Hubert A. Klein Ikkink");
    }
}

The compilation error:

$ javac -cp . Application.java
Application.java:8: error: changeUsername(String) is not public in User; cannot be accessed from outside package
user.changeUsername("Hubert A. Klein Ikkink");
^
1 error

The @PackageScope annotation can be used at class, field and method level. We can also add an argument to the annotation if applied at class level. We can then use the constants in groovy.transform.PackageScopeTarget to make all fields package scoped with FIELDS, all methods withMETHODS and the class with CLASS.

Code written with Groovy 2.2.1.

Developers! Quickly and easily gain access to the tools and information you need! Explore, test and combine our data quality APIs at Melissa Developer Portal – home to tools that save time and boost revenue. Our APIs verify, standardize, and correct the Big 4 + more – name, email, phone and global addresses – to ensure accurate delivery, prevent blacklisting and identify risks in real-time.

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}