Package groovy.transform
Annotation Interface ImmutableBase
Class annotation used to assist in the creation of immutable classes.
Checks on the validity of an immutable class and makes some preliminary changes to the class.
Usually used via the
@Immutable meta annotation.
Custom property handling:
- The
@ImmutableBaseannotation supports customization using@PropertyOptionswhich allows a custom property handler to be defined. This is most typically used behind the scenes by the@Immutablemeta-annotation but you can also define your own handler. If a custom handler is present, it will determine the code generated for the getters and setters of any property.
- Since:
- 2.5.0
- See Also:
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionbooleanIftrue, this adds a methodcopyWithwhich takes a Map of new property values and returns a new instance of the Immutable class with these values set.
-
Element Details
-
copyWith
boolean copyWithIftrue, this adds a methodcopyWithwhich takes a Map of new property values and returns a new instance of the Immutable class with these values set. Example:
Unknown keys in the map are ignored, and if the values would not change the object, then the original object is returned.@groovy.transform.Immutable(copyWith = true) class Person { String first, last } def tim = new Person( 'tim', 'yates' ) def alice = tim.copyWith( first:'alice' ) assert tim.first == 'tim' assert alice.first == 'alice'A key may also be a dotted nested path —
copyWiththen returns a new instance with that nested value updated, reusing the untouched branches (identity is preserved transitively):
Every node on a nested path must itself provide@groovy.transform.Immutable(copyWith = true) class Address { String city, zip }@groovy.transform.Immutable(copyWith = true) class Person { String name; Address address } def p = new Person('Alice', new Address('NYC', '10001')) def q = p.copyWith('address.city': 'Boston') assert q.address.city == 'Boston' assert q.address.zip == '10001'copyWith(Map)(e.g. an@Immutable/@RecordTypedeclared withcopyWith=true); otherwise a clear error is raised.A transactional block form is also generated, sugar over the map form. Within it,
oldis the original (pre-state) object — aligning witholdin@Ensures/@Contract— so values may be derived from it;prop.modify { }is a shorthand for the common transform-this-same-field case:def q = p.copyWith { name = 'Bob' // plain set address.city = old.address.city.reverse() // derive from pre-state loginCount.modify { it + 1 } // single-field shorthand }On a navigated pathmodifyis reserved by the block, so use theoldform (x = old.x.modify { ... }) to call a real same-named method on the value type — or simply when.modifywould read confusingly. If a method calledcopyWiththat takes a single parameter already exists in the class, then this setting is ignored, and no method is generated.- Default:
- false
-