Extending classes using Builder pattern

后端 未结 2 1516
攒了一身酷
攒了一身酷 2021-01-03 12:04

I am trying to extend a class a, into aX. So, I also extend aBuilder. However, while I am able to create an object of class a using :

aBuilder f = new aBuild         


        
相关标签:
2条回答
  • 2021-01-03 12:22

    You can solve your problem with generics, although it does require creation of an abstract superclass. Lurking on this site has taught me that inheriting from a concrete class is widely considered to be evil.

    public abstract class AbstractA {
        protected String s;
        protected int i;
        protected AbstractA() {
        }
        protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
            protected T object;
            protected B thisObject;
            protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
            protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
            protected ABuilder() {
                object = getObject();
                thisObject = thisObject();
            }
            public B withS(String s) {
                object.s = s;
                return thisObject;
            }
            public B withI(int i) {
                object.i = i;
                return thisObject;
            }
            public T build() {
                return object;
            }
        }
    }
    

    Once you have your abstract class together, you just extend it as many times as you need, overriding the abstract methods in the builder to return the type of object you need.

    public final class ConcreteA extends AbstractA {
        private String foo;
        protected ConcreteA() {
        }
        public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
            @Override protected ConcreteA getObject() {
                return new ConcreteA();
            }
            @Override protected Builder thisObject() {
                return this;
            }
            public Builder() {
            }
            public Builder withFoo(String foo) {
                object.foo = foo;
                return this;
            }
        }
    }
    

    Then... ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();

    0 讨论(0)
  • 2021-01-03 12:36

    withS(s) returns aBuilder, aBuilder does not have a method withB.

    Refactor required. Override withS etc in your sub class to return the correct type.

    (You don't normally explicitly instantiate builders, just reference them statically btw, and also a as a classname is bad)

    0 讨论(0)
提交回复
热议问题