具有非平凡子类树的Java builder模式
我熟悉将生成器模式用于泛型和子类,但我看不出如何使其与非平凡的子类树(即C扩展B扩展a)一起工作。下面是一个简单的例子,说明我正在尝试做什么:具有非平凡子类树的Java builder模式,java,generics,builder,Java,Generics,Builder,我熟悉将生成器模式用于泛型和子类,但我看不出如何使其与非平凡的子类树(即C扩展B扩展a)一起工作。下面是一个简单的例子,说明我正在尝试做什么: class A { private final int value; protected A(ABuilder builder) { this.value = builder.value; } public int getValue() { return value; } public sta
class A {
private final int value;
protected A(ABuilder builder) {
this.value = builder.value;
}
public int getValue() { return value; }
public static class ABuilder<T extends ABuilder<T>> {
private int value;
public T withValue(int value) {
this.value = value;
return (T) this;
}
public A build() {
return new A(this);
}
}
}
class B extends A {
private final String name;
public static BBuilder builder() {
return new BBuilder();
}
protected B(BBuilder builder) {
super(builder);
this.name = builder.name;
}
public String getName() { return name; }
public static class BBuilder<U extends BBuilder<U>> extends ABuilder<BBuilder<U>> {
private String name;
public U withName(String name) {
this.name = name;
return (U) this;
}
public B build() {
return new B(this);
}
}
}
不编译。有人能看出我做错了什么吗?我一直在尝试不同的泛型模式,但都没能成功
感谢所有有任何建议的人。看来您的错误只是声明了正确的参数:
class A {
private final int value;
public static <T extends Builder<T>> T builderA() {
return (T)new Builder<>();
}
protected A(Builder<? extends Builder<?>> builder) {
value = builder.value;
}
public static class Builder<T extends Builder<T>> {
private int value;
public T withValue(int value) {
this.value = value;
return (T)this;
}
public A build() {
return new A(this);
}
}
}
class B extends A {
private final String name;
public static <T extends Builder<T>> T builderB() {
return (T)new Builder<>();
}
protected B(Builder<? extends Builder<?>> builder) {
super(builder);
name = builder.name;
}
public static class Builder<T extends Builder<T>> extends A.Builder<T> {
private String name;
public Builder<T> withName(String name) {
this.name = name;
return this;
}
public B build() {
return new B(this);
}
}
}
你确定你需要仿制药吗?如果没有泛型,这种层次结构似乎可以正常工作
static class A {
protected final int value;
protected A(ABuilder builder) {
this.value = builder.value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "A{" +
"value=" + value +
'}';
}
public static ABuilder builder() {
return new ABuilder();
}
public static class ABuilder {
protected int value;
public ABuilder withValue(int value) {
this.value = value;
return this;
}
public A build() {
return new A(this);
}
}
}
static class B extends A {
protected final String name;
protected B(BBuilder builder) {
super(builder);
this.name = builder.name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "B{" +
"value=" + value +
", name='" + name + '\'' +
'}';
}
public static BBuilder builder() {
return new BBuilder();
}
public static class BBuilder extends ABuilder {
private String name;
public BBuilder withName(String name) {
this.name = name;
return this;
}
@Override
public BBuilder withValue(int value) {
this.value = value * 2;
return this;
}
public B build() {
return new B(this);
}
}
}
static class C extends B {
private final String otherName;
protected C(CBuilder builder) {
super(builder);
this.otherName = builder.otherName;
}
public String getName() {
return otherName;
}
@Override
public String toString() {
return "C{" +
"value=" + value +
", name='" + name + '\'' +
", otherName='" + otherName + '\'' +
'}';
}
public static CBuilder builder() {
return new CBuilder();
}
public static class CBuilder extends BBuilder {
private String otherName;
public CBuilder withName(String name) {
this.otherName = name;
return this;
}
public C build() {
return new C(this);
}
}
}
public void test() {
A a = A.builder().withValue(10).build();
B b = B.builder().withValue(10).withName("B").build();
C c = C.builder().withName("C").build();
System.out.println("a = "+a);
System.out.println("b = "+b);
System.out.println("c = "+c);
}
“既然我希望BBuilder由CBuilder扩展,“为什么?”
公共静态类ABuilder{…}
”-您如何在不使用子类化和原始类型的情况下正确定义该类型的变量?--“返回新的BBuilder();
”-这是一个原始类型。无论如何。。您不需要任何泛型,因为返回实例将始终是的子类ABuilder@MarcosVasconcelos问题在于方法链接:如果在BBuilder
上调用源于ABuilder
的方法,方法的返回类型将是一个ABuilder
,因此您限制了对可以从那里调用的方法的访问。。确实,我错过了ABuilder方法将返回ABuilder,这是一个很好的解决方案。两个问题:有没有办法删除对T
的强制转换returnnewbuilder()的推断类型是什么在builder()
-methods中的code>?是否有任何方法可以删除对T的强制转换-使用这种方法-而不是。也许不做生成器继承会更好。return new Builder()的推断类型是什么<代码>?扩展B.Builder
“?扩展B.Builder
”-有趣的是:如果用此类型替换菱形运算符,将得到编译器错误:错误:意外类型。。。必需:类或接口没有边界。。。发现:?扩展生成器
。在写这里之前,我已经检查了此代码。我没有任何编译错误,甚至没有警告。您可以检查它。:-)尝试复制粘贴它并在IDE中运行。我想你会得到同样的结果。你的代码是正确的。但您提供的推断类型不是。到目前为止,我无法在diamond中声明任何可以编译的类型。唯一需要编译的是菱形和原始类型。这个问题并不重要,我只是好奇而已。这种方法有一个缺点,就是你不得不用(所有)父类的…(…)-方法覆盖所有,并用样板代码填充这些方法。否则,方法链接将中断。@Turing85-我看不到这一点。查看我如何在C
中未使用值覆盖。也许你可以进一步解释。@Turing85-哦,等等-我明白你的意思了-调用CBuilder.withValue
返回一个BBuilder
-所以我同意没有那么有用。
class A {
private final int value;
public static <T extends Builder<T>> T builderA() {
return (T)new Builder<>();
}
protected A(Builder<? extends Builder<?>> builder) {
value = builder.value;
}
public static class Builder<T extends Builder<T>> {
private int value;
public T withValue(int value) {
this.value = value;
return (T)this;
}
public A build() {
return new A(this);
}
}
}
class B extends A {
private final String name;
public static <T extends Builder<T>> T builderB() {
return (T)new Builder<>();
}
protected B(Builder<? extends Builder<?>> builder) {
super(builder);
name = builder.name;
}
public static class Builder<T extends Builder<T>> extends A.Builder<T> {
private String name;
public Builder<T> withName(String name) {
this.name = name;
return this;
}
public B build() {
return new B(this);
}
}
}
A a = A.builder().withValue(1).build();
B b = B.builder().withValue(2).withName("xx").build();
static class A {
protected final int value;
protected A(ABuilder builder) {
this.value = builder.value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "A{" +
"value=" + value +
'}';
}
public static ABuilder builder() {
return new ABuilder();
}
public static class ABuilder {
protected int value;
public ABuilder withValue(int value) {
this.value = value;
return this;
}
public A build() {
return new A(this);
}
}
}
static class B extends A {
protected final String name;
protected B(BBuilder builder) {
super(builder);
this.name = builder.name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "B{" +
"value=" + value +
", name='" + name + '\'' +
'}';
}
public static BBuilder builder() {
return new BBuilder();
}
public static class BBuilder extends ABuilder {
private String name;
public BBuilder withName(String name) {
this.name = name;
return this;
}
@Override
public BBuilder withValue(int value) {
this.value = value * 2;
return this;
}
public B build() {
return new B(this);
}
}
}
static class C extends B {
private final String otherName;
protected C(CBuilder builder) {
super(builder);
this.otherName = builder.otherName;
}
public String getName() {
return otherName;
}
@Override
public String toString() {
return "C{" +
"value=" + value +
", name='" + name + '\'' +
", otherName='" + otherName + '\'' +
'}';
}
public static CBuilder builder() {
return new CBuilder();
}
public static class CBuilder extends BBuilder {
private String otherName;
public CBuilder withName(String name) {
this.otherName = name;
return this;
}
public C build() {
return new C(this);
}
}
}
public void test() {
A a = A.builder().withValue(10).build();
B b = B.builder().withValue(10).withName("B").build();
C c = C.builder().withName("C").build();
System.out.println("a = "+a);
System.out.println("b = "+b);
System.out.println("c = "+c);
}