Hello,
I have a set of classes like the following:
interface A { ... }
@Immutable @Modifiable @Style(deepImmutablesDetection = true) interface B extends A { ... }
@Immutable @Modifiable @Style(deepImmutablesDetection = true) interface C extends A { ... }
@Immutable @Modifiable @Style(deepImmutablesDetection = true) interface D { A getA(); ... }
What I'd like here is the ability to guarantee that calling getA() on an ImmutableD can only return an ImmutableB or an ImmutableC (and likewise for Modifiable).
It is currently possible to do this by adding a custom builder and custom modifiable implementation for D (as shown here). However, this isn't workable for my use case since D is used in a number of other classes with deepImmutablesDetection, each of which would then need need their own custom Modifiable class (to ensure the ModifiableD they have is of type D.Modifiable).
@Immutable @Modifiable @Value.Style(deepImmutablesDetection = true, overshadowImplementation = true, create = "new") interface D { A getA(); class CustomBuilder extends ImmutableD.Builder { @Override public D build() { D d = super.build(); if (d.getA() instanceof ModifiableB) { this.a(((ModifiableB) d.getA()).toImmutable()); return super.build(); } else if (d.getA() instanceof ModifiableC) { this.a(((ModifiableC) d.getA()).toImmutable()); return super.build(); } else { return d; } } } public static class Modifiable extends ModifiableD { @Override public Modifiable a(A a) { if (a instanceof ImmutableB) { super.a(ModifiableB.create().from((ImmutableB) a)); } else if (a instanceof ImmutableC) { super.a(ModifiableC.create().from((ImmutableC) a)); } else { super.a(a); } return this; } } ... }
I have a couple ideas for how an improvement to this could look:
- An annotation like
@DeepImmutableDetectedSubclasses(B.class, C.class)on eitherinterface Aor thegetAmethod that indicates which classes should be checked for converting Immutable<->Modifiable within the Modifiable and Builder implementations of D. This would very cleanly solve the issue I'm having, but it is admittedly only useful for my specific use case. - Add support for overriding the Modifiable version of a class (similar to the way
overshadowImplementation = trueallows this for Builder). This way, I could use the version of D above with custom builder and Modifiable implementations, butD.Modifiablewould automatically be used in other Immutables-generated code instead ofModifiableD.