For a long time we can annotate a class with the @Immutable
AST transformation so only an immutable instance of a class can be created. Since Groovy 2.2 we can use the annotation parameter copyWith
. If we set the value of this parameter to true
the AST transformation generates a new method copyWith()
in the class. The method returns a new immutable instance of the class. We can pass a map with property names and values we want to set in the newly created instance.
In the following sample code we create a new immutable class User
and we use the @Immutable
annotation and set the parameter copyWith
to true
:
import groovy.transform.Immutable @Immutable(copyWith = true) class User { String name String email } // Create immutable instance of User. def mrhaki = new User('mrhaki', 'mrhaki@mrhaki.com') mrhaki.with { assert name == 'mrhaki' assert email == 'mrhaki@mrhaki.com' } // Use new copyWith method to create a new immutable // instance of the User class where name property // is changed and email property is unchanged. def hubert = mrhaki.copyWith(name: 'Hubert A. Klein Ikkink') hubert.with { assert name == 'Hubert A. Klein Ikkink' assert email == 'mrhaki@mrhaki.com' } // The properties are still immutable: try { hubert.email = 'new-mail@host.nl' } catch (ReadOnlyPropertyException e) { assert 'Cannot set readonly property: email for class: User' == e.message }
Code written with Groovy 2.2.