I am trying to extend a class a, into aX. So, I also extend aBuilder. However, while I am able to create an object of class a using :
aBuilder f = new aBuilder();
f.bi = i;
f.bs = s;
a atry = f.withI(i).withS(s).build();
The same doesn't work for aX. When I try to do this :
aXBuilder fb = new aXBuilder();
aX aXtry = fb.withI(i).withS(s).withB(b).build();
I get an error (The method withB(Boolean) is undefined for the type a.aBuilder). Should I instead rewrite all the stuff for aX, instead of simply adding new stuff? I don't want to do that because that will lead to a lot of duplicacy in my code. The classes a and aX are as given below:
class a {
protected String s;
protected int i;
public void getdata() {
System.out.println(this.s);
System.out.println(this.i);
}
protected a(aBuilder fb) {
this.s = fb.bs;
this.i = fb.bi;
}
public static class aBuilder {
public aBuilder() {
}
protected String bs;
protected int bi;
public aBuilder withS(String s) {
this.bs = s;
return this;
}
public aBuilder withI(Integer i) {
this.bi = i;
return this;
}
public a build() {
return new a(this);
}
}
}
class aX extends a {
protected Boolean b;
public void getData()
{
System.out.println(this.s);
System.out.println(this.i);
System.out.println(this.b);
}
protected aX(aXBuilder axb) {
super(axb);
this.b = axb.bb;
}
public static class aXBuilder extends aBuilder {
protected Boolean bb;
public aXBuilder() {
}
public aXBuilder withB(Boolean b) {
this.bb = b;
return this;
};
public aX build() {
return new aX(this);
}
}
}
withS(s)
returnsaBuilder
,aBuilder
does not have a methodwithB
.Refactor required. Override
withS
etc in your sub class to return the correct type.(You don't normally explicitly instantiate builders, just reference them statically btw, and also a as a classname is bad)
You can solve your problem with generics, although it does require creation of an abstract superclass. Lurking on this site has taught me that inheriting from a concrete class is widely considered to be evil.
Once you have your abstract class together, you just extend it as many times as you need, overriding the abstract methods in the builder to return the type of object you need.
Then...
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();