If you just want to reduce the amount of copy code you have to write, you can use reflection to copy the members with the same names, see Copy fields between similar classes in java - Stack Overflow.
However, if you want provide other coders with different abstractions without the overhead of copying, you can maintain a single package level implementation class that implements multiple public interfaces, which provide different degrees of access to the same object created by this class. Besides, provide necessary factory methods and conversion utility functions. Code outside the package can manipulate objects of these interfaces instead of that class and perform necessary conversion.
See the code below:
public interface AComplex {
T1 getT1();
T2 getT2();
T3 getT3();
// ...
}
public interface ASimpleV1 {
T1 getT1();
T2 getT2();
}
public interface ASimpleV2 extends ASimpleV1 {
T3 getT3();
}
class AImpl implements AComplex, ASimpleV1, ASimpleV2 {
T1 t1;
T2 t2;
T3 t3;
@Override
public T1 getT1() {
return t1;
}
@Override
public T2 getT2() {
return t2;
}
@Override
public T3 getT3() {
return t3;
}
// ...
}
public final class As {
private As() {
}
public static ASimpleV1 newASimpleV1() {
return new AImpl();
}
public static ASimpleV1 newASimpleV1(T1 t1, T2 t2) {
return new AImpl(t1, t2, null);
}
// ...
public static ASimpleV2 ASimpleV1AsASimpleV2(ASimpleV1 aSimpleV1) {
return (ASimpleV2) aSimpleV1;
}
public static ASimpleV2 ASimpleV1AsASimpleV2(ASimpleV1 aSimpleV1, T3 t3) {
AImpl aImpl = (AImpl) aSimpleV1;
aImpl.t3 = t3;
return (ASimpleV2) aImpl;
}
public static ASimpleV1 ASimpleV2AsASimpleV1(ASimpleV1 aSimpleV2) {
return (ASimpleV1) aSimpleV2;
}
// ...
}
Note that AImpl
and its member variables are of package level visibility, so code outside the package can not operate on its members directly, except using reflection of course.
For simplicity I have only written getters, you can also add setters and other methods as needed.