Suppose I need some DerivedBuilder to extend some BaseBuilder. Base builder has some method like foo (which returns BaseBuilder). Derived builder has method bar. Method bar should be invoked after method foo. In order to do it I can override foo method in DerivedBuilder like this:
@Override
public DerivedBuilder foo() {
    super.foo();
    return this;
}
The problem is that BaseBuilder has a lot of methods like foo and I have to override each one of them. I don't want to do that so I tried to use generics:
public class BaseBuilder<T extends BaseBuilder> {
    ...
    public T foo() {
        ...
        return (T)this;
    }
}
public class DerivedBuilder<T extends DerivedBuilder> extends BaseBuilder<T> {
    public T bar() {
        ...
        return (T)this;
    }
}
But the problem is that I still can not write
new DerivedBuilder<DerivedBuilder>()
        .foo()
        .bar()
Even though T here is DerivedBuilder. What can I do in order to not to override a lot of functions?
Your problem is the definition of DerivedBuilder:
class DerivedBuilder<T extends DerivedBuilder>;
And then instantiating it with a type erased argument new DerivedBuilder<DerivedBuilder<...what?...>>().
You'll need a fully defined derived type, like this:
public class BaseBuilder<T extends BaseBuilder<T>> {
    @SuppressWarnings("unchecked")
    public T foo() {
        return (T)this;
    }
}
public class DerivedBuilder extends BaseBuilder<DerivedBuilder> {
    public DerivedBuilder bar() {
        return this;
    }
}
Check ideone.com.
In addition to BeyelerStudios's answer, if you want to nest further, you can just use this:
class Base<T extends Base<?>> {
    public T alpha() { return (T) this; }
    public T bravo() { return (T) this; }
    public T foxtrot() { return (T) this; }
}
class Derived<T extends Derived<?>> extends Base<T> {
    public T charlie() { return (T) this; }
    public T golf() { return (T) this; }
}
class FurtherDerived<T extends FurtherDerived<?>> extends Derived<T> {
    public T delta() { return (T) this; }
    public T hotel() { return (T) this; }
}
class MuchFurtherDerived<T extends MuchFurtherDerived<?>> extends FurtherDerived<T> {
    public T echo() { return (T) this; }
}
public static void main(String[] args) {
    new MuchFurtherDerived<MuchFurtherDerived<?>>()
        .alpha().bravo().charlie().delta().echo().foxtrot().golf().hotel()
        .bravo().golf().delta().delta().delta().hotel().alpha().echo()
        .echo().alpha().hotel().foxtrot();
}
                        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