java - 使用泛型初始化子类Builder作为父构建器的类型

时间:2018-02-09 19:29:56

标签: java generics inheritance abstract-class builder

我在父类和子类中都有构建器。父级具有抽象构建器和扩展抽象构建器的具体构建器。子项具有一个抽象构建器,用于扩展父抽象构建器和扩展子抽象构建器的具体构建器。这样做的原因是父级的setter返回当前的Builder类。我有方法返回类自己的抽象构建器类型,我想将其称为父抽象类型(在其上调用父方法)。我可以上班的只有ParentBuilder<? extends ParentBuilder<?>>,但由于通配符,这看起来并不好。这是一个可以更好地解释它的例子。

我想在主要代码中做些什么:

ParentBuilder<? extends ParentBuilder<?> builder; // How to do this?
if (something) {
    builder = Child.doSomething();
}
else {
    builder = new Parent.builder();
}

Parent p = builder.setThing1("foo").build();

在Parent.java中

public class Parent {

    private final String thing1;

    protected <B extends ParentBuilder<B>> Parent(final B builder) {
        this.thing1 = builder.thing1;
    }

    public String getThing1() {
        return this.thing1;
    }

    protected abstract static class ParentBuilder<B extends ParentBuilder<B>> {
        protected final Class<B> builderClass;
        protected String thing1;

        protected ParentBuilder(final Class<B> builderClass) {
            this.builderClass = builderClass;
        }

        public B setThing1(final String thing1) {
            this.thing1 = thing1;
            return builderClass.cast(this);
        }

        public abstract Parent build();
    }

    public static class Builder extends ParentBuilder<Builder> {
        public Builder() {
            super(Builder.class);
        }

        @Override
        public Parent build() {
            return new Parent(this);
        }
    }
}

在Child.java中

public class Child extends Parent {

    private final String thing2;

    protected <B extends ChildBuilder<B>> Child(final B builder) {
        super(builder);
        this.thing2 = builder.thing2;
    }

    public String getThing2() {
        return this.thing2;
    }

    public static Builder doThings(/*...*/) {
        //...
        return new Child.Builder();
    }

    protected abstract static class ChildBuilder<B extends ParentBuilder<B>> extends ParentBuilder<B> {
        protected String thing2;

        protected ChildBuilder(final Class<B> builderClass) {
            super(builderClass);
        }

        public B setThing2(final String thing2) {
            this.thing2 = thing2;
            return builderClass.cast(this);
        }
    }

    public static class Builder extends ChildBuilder<Builder> {
        public Builder() {
            super(Builder.class);
        }

        @Override
        public Child build() {
            return new Child(this);
        }
    }
}

在第一部分中,我将构建器声明为父抽象构建器类型,但我不确定键入该对象的正确方法。通配符似乎不对。我想到的一个选项是在抽象构建器上面创建一个接口,然后我可以使用该类型。但是拥有界面似乎很麻烦 - &gt;抽象类 - &gt;父类和每个子类中的具体类。有没有人有任何其他建议?谢谢。

1 个答案:

答案 0 :(得分:1)

以下是使用您的设置的工作代码:

Parent.ParentBuilder<?> builder; 

if ( something ) {
    builder = new Child.Builder();
}
else {
    builder = new Parent.Builder();
}

Parent p = builder.setThing1("foo").build();

现在,如果您希望builder.build()在没有强制转换的情况下返回Child,则需要更改现有的构建器泛型类型声明。