当前位置: 首页 > 知识库问答 >
问题:

具有继承支持的泛型问题的生成器模式

东博瀚
2023-03-14

我基于这个答案实现了模式,我有以下asbtract配置:

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行我得到-找不到符号方法setHeight。我的错误是什么?

编辑 - 我将有一个扩展的诊断配置,必须扩展对话框配置等。我的意思是会有其他子类。

共有2个答案

韩阳飙
2023-03-14

我发现了我的错误。这是我如何使用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();

请注意<code>

慕仲渊
2023-03-14

您首先将<code>setCalories()

public Builder<B> setCalories(int calories) {
  this.calories = calories;
  return this;
}

去掉强制转换和警告。现在仔细看看这个。您返回一个Builder。这段代码不知道未来的子类。它只返回该基础构建器的一个实例。

因此,当您具有该链接调用时:

 .setHeight(0) .build();

这将返回该基础构建器。然后调用 build() - 这将构建一个抽象配置。但是您希望将其分配给更具体的对话配置。因此,错误。

一个(丑陋的)解决方法:

DialogConfig.DialogConfigBuilder<?> builder = new DialogConfig.DialogConfigBuilder<>().setHeight(0);
builder.setCalories(0);

...config = builder.build();

还有一个解决方案——再次修改< code > setcales():

@SuppressWarnings("unchecked")
public <T extends B> T setCalories(int calories) {
  this.calories = calories;
  return (T) this;
}

修复编译错误;并且还允许链接<code>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);
    }
}
 类似资料:
  • 问题内容: 我想将一个Web服务URL请求表示为一个对象,并发现在继承层次结构中可能有很多通用参数。一个请求可以有很多参数,一些是必选参数,而其他是可选参数,我相信Bloch的Builder模式是一个不错的选择,它可以使用流畅的接口模拟命名参数。 具体来说,我正在设计Google Maps网络服务API,该API具有常规的网络服务请求 和是必填参数,也是必填参数。还有一个可选参数。 每个服务都有其

  • 问题内容: 我有三节课: 现在在我的主要职能中,我做这样的事情: 但这会产生2个编译时错误: 无法将A转换为fileHandler 无法将B转换为fileHandler 如果基类不是泛型的,那么我如何摆脱这些错误呢? 更新: 我的班级层次结构是: 调用函数的C类或 调用函数的D类。 C和D都从抽象类E派生。 现在,我应该如何在C和D以及E中定义这些功能: 我给出了以下内容: E: C: D: C,

  • 问题内容: 我正在编写一个流畅的API,以配置和实例化一系列“消息”对象。我有消息类型的层次结构。 为了在使用Fluent API时能够访问子类的方法,我使用了泛型来对子类进行参数化,并使所有的fluent方法(以“ with”开头)都返回泛型类型。注意,我省略了流利方法的大部分内容。其中进行了许多配置。 具体的子类类似地重新定义泛型。 该代码有效,即,我可以实例化任何类并使用所有流利的方法: 以

  • 问题内容: 我的对象层次结构随着继承树的加深而增加了复杂性。这些都不是抽象的,因此,它们的所有实例都或多或少地达到了目的。 由于参数数量很多,我想使用“构建器模式”来设置属性,而不是对多个构造函数进行编码。由于我需要适应所有排列,因此继承树中的叶类将具有伸缩构造函数。 当我在设计过程中遇到一些问题时,我已经浏览了这里的答案。首先,让我给您一个简单的,简短的示例来说明问题。 现在我们有一些代码可以继

  • Java Lombok库:继承的生成器注释问题 创建子类的实例时,父类属性在生成器注释中不可见。 以下失败: 然而,下面的说法是正确的: 似乎这个问题已经存在很长时间了,不知道最新版本是否有任何修正。

  • 我有一个Spring Boot(kotlin)项目,我使用springdoc openapi生成openapi 3规范。我的数据模型如下所示: 还有一个简单的控制器,如下所示: 生成的yaml为: 这里的问题是我的控制器可以返回或,这在返回类型中指定。我期望生成的模式是: 有没有办法做到这一点?