Reading the "The Well-Grounded Java Developer" book by Benjamin J. Evans and Martijn Verburg I've encountered the following example in Groovy:
class Character {
private int strength
private int wisdom
}
def pc = new Character(strength: 10, wisdom: 15)
pc.strength = 18
println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"
The output of the snippet is the following:
STR [18] WIS [15]
Till now there is no questions. The code above have been slightly modified with the @Immutable
annotation, as the book suggests:
import groovy.transform.*
@Immutable
class Character {
private int strength
private int wisdom
}
def pc = new Character(strength: 10, wisdom: 15)
pc.strength = 18
println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"
The output of the last snippet is still the same:
STR [18] WIS [15]
The expected result is anything but not like the one above...
Why does an object of an immutable class seem to act like a mutable one? Does conception of immutability in Groovy permit modification to class fields?
In order to fix the issue that you reported is simple which is removing access modifier to fields
. That should fix the issue.
import groovy.transform.Immutable
@Immutable
class Character {
int strength
int wisdom
}
def pc = new Character(strength: 10, wisdom: 15)
pc.strength = 18
println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"
Now, it will raise an exception, saying below :
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: strength for class: Character
at Character.setProperty(Script1.groovy)
at Script1.run(Script1.groovy:10)
If you want more details on why the behavior is different, please refer here
This behaviour is expected when explicitly setting the fields to private
. The docs for Immutable
state:
You don't have to follow Groovy's normal property conventions, e.g. you can create an explicit private field and then you can write explicit get and set methods. Such an approach, isn't currently prohibited (to give you some wiggle room to get around these conventions) but any fields created in this way are deemed not to be part of the significant state of the object and aren't factored into the equals or hashCode methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With