Reputation: 12998
Given
import groovy.transform.Immutable
class A {
String a
}
@Immutable
class B extends A {
String b
}
When I try to set the values using the map constructor
def b = new B(a: "a", b: "b")
then a
ist still null:
groovy:000> b = new B(a: "a", b: "b")
===> B(b)
groovy:000> b.b
===> b
groovy:000> b.a
===> null
Is it possible to define an @Immutable
class which considers the properties of its super classes in the map constructor?
I am using Groovy 2.4.3
Upvotes: 5
Views: 1126
Reputation: 3488
I have run across this as well. You can get around it by calling the getter method groovy auto adds for you on the property instead of directly accessing the property (in your example b.getA() instead of b.a )
Here's a stupid example....
class base{
def name;
def myNameIs(){
return name;//willl return null when called from extending class person
}
def extendersNameIs(){
return getName()// will return extending class default value
}
}
class person extends base{
def name="betty"//override set default value
}
def m=new person();
println m.myNameIs(); // outputs null
println m.extendersNameIs();//outputs "betty"
See it in action https://groovyconsole.appspot.com/script/5193965758316544 This isn't always an ideal solution, but it's a workaround.
Upvotes: 0
Reputation: 5883
Based on the code for the ImmutableASTTransformation, the Map-arg constructor added by the createConstructorMapCommon
method does not include a call to super(args)
in the method body.
I'm not sure if this omission is intentional or accidental; regardless, this class would need to be modified in order to achieve what you're looking for. In the meantime, my only suggestion is to use composition instead of inheritance with @Delegate
to simplify access to A
's properties.
import groovy.transform.*
@TupleConstructor
class A {
String a
}
@Immutable(knownImmutableClasses=[A])
class B {
@Delegate A base
String b
}
def b = new B(base: new A("a"), b: "b")
println b.a
However, since A
is mutable (even though we declare it immutable in the @Immutable
annotation, B
becomes mutable, too, e.g.
b.a = 'foo' // succeeds
Upvotes: 4