>我基于这个答案实现了模式 我有以下摘要配置:
public abstract class AbstractConfig {
public static abstract class Builder<B extends Builder<B>> {
private int calories = 0;
public Builder() {
}
public B setCalories(int calories) {
this.calories = calories;
return (B) this;
}
public abstract AbstractConfig build();
}
private int calories = 0;
protected AbstractConfig(final Builder builder) {
calories = builder.calories;
}
}
我有以下具体配置:
public class DialogConfig extends AbstractConfig {
public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> {
private double width;
private double height;
public DialogConfigBuilder() {
//does nothing.
}
public B setWidth(final double value) {
width = value;
return (B) this;
}
public B setHeight(final double value) {
height = value;
return (B) this;
}
public DialogConfig build() {
return new DialogConfig(this);
}
}
private final double width;
private final double height;
protected DialogConfig(final DialogConfigBuilder builder) {
super(builder);
width = builder.width;
height = builder.height;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
}
这就是我使用它的方式
DialogConfig config = new DialogConfig.DialogConfigBuilder()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
在 X 行我得到 - 找不到符号方法集高度。我的错误是什么?
编辑- 我将有一个扩展对话框配置,必须扩展对话框配置等。我的意思是会有其他子类。
首先将setCalories()
更改为:
public Builder<B> setCalories(int calories) {
this.calories = calories;
return this;
}
摆脱那个演员和警告。现在仔细看看这个。您返回一个生成器。此代码不知道未来的子类。它只返回该基础构建器的一个实例。
因此,当您有该链式调用时:
.setHeight(0) .build();
这将返回该基础构建器。然后调用build()
- 这将构建一个抽象配置。但是您希望将其分配给更具体的 DialogConfig。因此错误。
一个(丑陋的(解决方法:
DialogConfig.DialogConfigBuilder<?> builder = new DialogConfig.DialogConfigBuilder<>().setHeight(0);
builder.setCalories(0);
...config = builder.build();
还有一个解决方案- 通过再次返工setCalories()
:
@SuppressWarnings("unchecked")
public <T extends B> T setCalories(int calories) {
this.calories = calories;
return (T) this;
}
修复编译错误;并允许链接setCalories()
调用。摆脱投射/抑制的最后练习留给读者作为练习。
并记录在案 - "完整"解决方案,包括摆脱原始类型和其他警告的所有调整:
abstract class AbstractConfig {
public static abstract class Builder<B extends Builder<B>> {
private int calories = 0;
@SuppressWarnings("unchecked")
public <T extends B> T setCalories(int calories) {
this.calories = calories;
return (T) this;
}
public abstract AbstractConfig build();
}
private int calories = 0;
public int getCalories() { return calories; }
protected <B extends Builder<B>> AbstractConfig(final Builder<B> builder) {
calories = builder.calories;
}
}
final class DialogConfig extends AbstractConfig {
public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> {
private double width;
private double height;
public DialogConfigBuilder<B> setWidth(final double value) {
width = value;
return this;
}
public DialogConfigBuilder<B> setHeight(final double value) {
height = value;
return this;
}
public DialogConfig build() {
return new DialogConfig(this);
}
}
private final double width;
private final double height;
protected <B extends DialogConfigBuilder<B>> DialogConfig(final DialogConfigBuilder<B> builder) {
super(builder);
width = builder.width;
height = builder.height;
}
public double getWidth() { return width; }
public double getHeight() { return height; }
}
public class Builders {
public static void main(String[] args) {
DialogConfig config = new DialogConfig.DialogConfigBuilder<>().setHeight(0).setCalories(0).build();
System.out.println(config);
}
}
我发现了我的错误。这就是我使用DialogConfigBuilder的方式
DialogConfig config = new DialogConfig.DialogConfigBuilder()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
这就是我应该如何使用DialogConfigBuilder
DialogConfig config = new DialogConfig.DialogConfigBuilder<>()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
在第二种情况下注意<>
。