Search code examples
javagenericsbuilder

Subclassing a subclass of a (generic) builder


I'm trying to implement a builder object with multi-level inheritance. I took some inspiration from Subclassing a Java Builder class and this is my (simplified) code:

public class StackOverflow {
    public static class Builder<T extends Builder<T>> {
        public Builder() {}

        public T doA() {
            System.out.println("A");
            return (T) this;
        }
    }

    public static class BuilderSubclass <T extends BuilderSubclass<T>> 
            extends Builder<BuilderSubclass<T>> {

        public BuilderSubclass() {}

        public T doB() {
            System.out.println("B");
            return (T) this;
        }
    }

    public static class BuilderSubclassSubclass
            extends BuilderSubclass<BuilderSubclassSubclass> {

        public BuilderSubclassSubclass() {}

        public BuilderSubclassSubclass doC() {
            System.out.println("C");
            return this;
        }
    }
}

I would like do something like this: new StackOverflow.BuilderSubclassSubclass().doA().doC().doB()

However, when I call new StackOverflow.BuilderSubclassSubclass().doA(), the returned object is not a BuilderSubclassSubclass but a BuilderSubclass<BuilderSubclassSubclass>. I know why this is the case: Builder's generic type is BuilderSubclass<BuilderSubclassSubclass> which is assigned in the class signature of BuilderSubclass.

Any ideas on how I can avoid this problem?

Update: I guess I could avoid using the builder pattern, and instead call the functions like this:

StackOverflow.BuilderSubclassSubclass builder = new StackOverflow.BuilderSubclassSubclass();
builder.doA();
builder.doB();
builder.doC();

In which case the code becomes:

public class StackOverflowBatchHelperFunctions {
    public static class Builder {

        public Builder() {
        }

        public void doA() {
            System.out.println("A");
        }
    }

    public static class BuilderSubclass extends Builder {
        public BuilderSubclass() {
            super();
        }

        public void doB() {
            System.out.println("B");
        }
    }

    public static class BuilderSubclassSubclass extends BuilderSubclass {
        public BuilderSubclassSubclass() {
            super();
        }

        public void doC() {
            System.out.println("C");
        }
    }
}

However I think this is less "pretty", so I would still love to see an answer to the initial problem.


Solution

  • You should replace public static class BuilderSubclass<T extends BuilderSubclass<T>> extends Builder<BuilderSubclass<T>> with public static class BuilderSubclass<T extends BuilderSubclass<T>> extends Builder<T>.