I'm trying to have an abstract base class for some builder classes so I can easily reuse code between the Builder implementations. I want my builders to support method chaining therefore a method has to return "this" instance of the most specific type. I figured I could probably do this with generics. Unfortunatly I did not manage to do it without using unsafe operations. Is it possible?
Sample code of how I'm trying it (and how it works) below. I'd like to avoid casting to T in "foo()" (which causes an unchecked warning), can this be done?
public class Builders { public static void main( final String[] args ) { new TheBuilder().foo().bar().build(); } } abstract class AbstractBuilder<T extends AbstractBuilder<?>> { public T foo() { // set some property return (T) this; } } class TheBuilder extends AbstractBuilder<TheBuilder> { public TheBuilder bar() { // set some other property return this; } public Object build() { return new Object(); } }
An abstract class can have one or multiple number of unimplemented methods. As an abstract class is not proper, or does not have ideally defined methods compared to a regular class, so abstract classes cannot be instantiated, that means we cannot create any direct objects of abstract classes.
Abstract class in Java is similar to interface except that it can contain default method implementation. An abstract class can have an abstract method without body and it can have methods with implementation also. abstract keyword is used to create a abstract class and method.
Abstract class: is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class). Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the subclass (inherited from).
A normal class(non-abstract class) cannot have abstract methods.
You want to declare T
as extends AbstractBuilder<T>
in AbstractBuilder
.
Use an abstract protected
method to get this
of type T
.
abstract class AbstractBuilder<T extends AbstractBuilder<T>> { protected abstract T getThis(); public T foo() { // set some property return getThis(); } } class TheBuilder extends AbstractBuilder<TheBuilder> { @Override protected TheBuilder getThis() { return this; } ... }
Alternatively, drop the generic type parameter, rely on covariant return types and make the code cleaner for clients (although usually they would be using TheBuilder
rather than the largely implementation detail of the base class), if making the implementation more verbose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With