1

I have a builder interface:

@ParametersAreNonnullByDefault
public interface ILoadableBuilder<C extends ILoadable,T extends ILoadableBean> {
    public @Nonnull T getState();
    public @Nonnull <B extends ILoadableBuilder<C,T>> B setComponentClass(final Class<C> componentClass);
    public @Nonnull <B extends ILoadableBuilder<C,T>> B setDriver(final WebDriver driver);
    public @Nonnull <B extends ILoadableBuilder<C,T>> B setLoadTimeoutInSeconds(final @Nonnegative int loadTimeoutInSeconds);
    public @Nonnull <B extends ILoadableBuilder<C,T>> B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator);
}

and this implementation:

@ParametersAreNonnullByDefault
public class LoadableBuilder<C extends ILoadable,T extends ILoadableBean,B extends ILoadableBuilder<C,T>> implements
        ILoadableBuilder<C,T> {   

    private final @Nonnull T componentBean;
    private @Nullable IEnumeratorBean<? extends IEnumerable<?>,?> enumerator;
    private @Nullable Class<C> componentClass;

    public LoadableBuilder(final T componentBean) {
        this.componentBean = componentBean;
    }

    @Override
    public final @Nonnull T getState() {
        return componentBean;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final @Nonnull B setComponentClass(final Class<C> componentClass) {
        this.componentClass = componentClass;
        return (B)this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final @Nonnull B setDriver(final WebDriver driver) {
        getState().setDriver(driver);
        return (B)this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final @Nonnull B setLoadTimeoutInSeconds(final @Nonnegative int loadTimeoutInSeconds) {
        getState().getLoadTimeoutInSeconds();
        return (B)this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public @Nonnull B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator) {
        this.enumerator = enumerator;
        return (B)this;
    }

    public @Nullable Class<C> getComponentClass() {
        return componentClass;
    }
}

The compiler complains about the setComponentClass method and the setEnumeratorMethod in the implementation class -- It says that they do not override the methods in the interface, but it does not complain about any of the other methods which are implemented in the same way with the same return value. Why are these two methods a problem for the compiler but the others are not?

Compiler errors:

Error:(16, 8) java: com.someplace.api.ui.LoadableBuilder is not abstract and does not override abstract method <B>setEnumerator(com.someplace.api.ui.IEnumeratorBean<? extends com.someplace.api.dsl.IEnumerable<?>,?>) in com.someplace.api.ui.ILoadableBuilder
Error:(47, 29) java: name clash: setComponentClass(java.lang.Class<C>) in com.someplace.api.ui.LoadableBuilder and <B>setComponentClass(java.lang.Class<C>) in com.someplace.api.ui.ILoadableBuilder have the same erasure, yet neither overrides the other
Error:(46, 5) java: method does not override or implement a method from a supertype
Error:(68, 23) java: name clash: setEnumerator(com.someplace.api.ui.IEnumeratorBean<? extends com.someplace.api.dsl.IEnumerable<?>,?>) in com.someplace.api.ui.LoadableBuilder and <B>setEnumerator(com.someplace.api.ui.IEnumeratorBean<? extends com.someplace.api.dsl.IEnumerable<?>,?>) in com.someplace.api.ui.ILoadableBuilder have the same erasure, yet neither overrides the other
Error:(67, 5) java: method does not override or implement a method from a supertype
Selena
  • 2,208
  • 8
  • 29
  • 49
  • Methods in an `interface` are `public` by default... – Boris the Spider Feb 22 '15 at 20:37
  • I know that. I just like to be explicit just in case less experienced Java developers are working with my code. – Selena Feb 22 '15 at 20:39
  • 3
    Redundant modifiers serve to confuse, not help. – Boris the Spider Feb 22 '15 at 20:40
  • 2
    With an `ILoadableBuilder`, I can do `builder.setComponentClass(Class4.class);`, and `builder.setComponentClass(Class4.class);` i.e. I can call setComponentClass with two different type parameters on the same instance. I can't do that with a LoadableBuilder. – user253751 Feb 22 '15 at 20:42
  • Hmmm. Okay, so that is not what I intended with the interface type. I was attempting to get an extensible builder interface and implementation such that subclasses of the interface could add their own setters and the the return values be of the correct sub-class type, regardless of whether the setter was in the superclass or the subclass. – Selena Feb 22 '15 at 20:47
  • Can you give the full compiler error? – RealSkeptic Feb 22 '15 at 20:48
  • But then why doesn't the compiler complain about the other setter methods? – Selena Feb 22 '15 at 20:48
  • Compiler error messages have been added to the question. – Selena Feb 22 '15 at 20:58
  • Please see this question/answer: http://stackoverflow.com/questions/28645730/builder-pattern/28647016#28647016 It accomplishes what you want with an abstract class instead of an interface, but the concepts are the same. – fps Feb 22 '15 at 21:05

0 Answers0