First of all, I'm relatively new to Java, so may be what I am asking is trivial, but I could not find an answer here or in other place.
For simplicity, let's assume I have the following class hierarchy:
class Shape {
protected Shape(double x, double y) {...}
}
class Circle extends Shape {
public Circle(double radius) {...}
}
class Rectangle extends Shape {
public Rectangle(double edge) {...}
}
I'd like to use a builder pattern for each shape. So I added Builders to each one of them:
class Shape {
protected static abstract class BuilderBase<T extends BuilderBase<T, S>, S extends Shape> {
public T setLocation(double x, double y) {
// ...
return (T)this; // ? - is there a way to avoid this casting?
}
public abstract S build();
}
protected Shape(/*...*/) {/*...*/}
}
class Circle extends Shape {
public static class Builder extends BuilderBase<Builder, Circle> {
public Builder setRadius(double radius) {
//...
return this;
}
@Override
public Circle build() { return new Circle(/*...*/); }
}
private Circle(/*...*/) {/*...*/}
}
class Rectangle extends Shape {
public static class Builder extends BuilderBase<Builder, Rectangle> {
public Builder setRadius(double radius) {
//...
return this;
}
@Override
public Rectangle build() {
return new Rectangle(/*...*/);
}
}
public Rectangle(/*...*/) {/*...*/}
}
EDIT: Generic here was used in order to allow using Builder methods in any order. For example, in order to allow the following call:
new Circle.Builder()
.setLocation(0, 0)
.setRadius(10)
.build();
My problem is in this casting:
public T setLocation(double x, double y) {
// ...
return (T)this; // ? - is there a way to avoid this casting?
}
I'm struggling to find a way to avoid this casting. The only way I found till now was to add yet another abstract method to the BaseBuilder method:
protected static abstract class BuilderBase<T extends BuilderBase<T, S>, S extends Shape> {
protected abstract T getBuilder();
public T setLocation(double x, double y) {
// ...
return getBuilder();
}
//...
}
So each derived builder will have to implement it:
@Override
protected Circle getBuilder() {
return this;
}
It seems to me as overkill but I don't want to get compilation warnings.
Question: is there any more elegant way to avoid the casting?
You can’t avoid having a little bit of additional code per subclass but you can avoid having an unchecked cast. Just create an
abstractmethod responsible for returning an appropriately typedthis. This method has to be implemented by concrete subclasses once but can be used for all methods of the base class which ought to returnthis: