【问题标题】:Best handling of constructor with default values具有默认值的构造函数的最佳处理
【发布时间】:2023-03-25 12:22:01
【问题描述】:

我有多个属性的类都具有默认值。这些属性不是可选的,它们是必需的,但具有默认值。例如:

String fillColor = "White";
String borderColor = "Blue";
int size = 10;

只有一个构造函数并在需要默认值时传入空值是不好的做法吗?

Object myObject = new Object(null, null, 15);

另外,我正在考虑可能实现一个构建器。

【问题讨论】:

    标签: java constructor overloading


    【解决方案1】:

    这是一个判断电话。

    想象一下,一个不太了解您的课程的人正在阅读代码。他们能理解这两个nulls 是什么意思吗?他们可能必须查找构造函数并查看这些参数是什么。即使是熟悉的用户也可能很难记住是填充颜色还是边框颜色先出现。

    这些是拥有更多构造函数甚至使用构建器类的好论据。额外的构造函数允许完全省略未使用的参数。

    Object(int size);
    Object(String fillColor, String borderColor);
    Object(String fillColor, String borderColor, int size);
    

    缺点是您必须为每个省略参数组合使用不同的构造函数。如果有很多组合,它可能会变得笨拙。在 n 参数的最坏情况下,您可能必须提供 2n 个构造函数。

    如果用户想设置一种颜色而不是另一种颜色,这也无济于事。

    Object(String fillColor);     // ambiguous overloads
    Object(String borderColor);
    

    构建器提供最大的灵活性。设置是相互独立设置的,避免了前面描述的指数膨胀。具有相同类型的设置不再模棱两可。填充颜​​色和边框颜色都是字符串不是问题:

    class ObjectBuilder {
        ObjectBuilder fillColor(String fillColor);
        ObjectBuilder borderColor(String borderColor);
        Objectbuilder size(int size);
        Object build();
    }
    

    权衡是增加了代码复杂性。构建器类需要大量的工作来创建。它还使构造更加冗长,可能是积极的消极的。用你最好的判断。

    【讨论】:

      【解决方案2】:

      只有一个构造函数并在需要默认值时传入空值是不好的做法吗?

      是的。您假设阅读代码的人会知道“null 表示默认值”,而不是例如他们实际上希望这些值为空。

      添加一个您可以调用的重载,而无需使用无意义的文字空值:

      Object myObject = new Object(15);
      

      调用另一个构造函数:

      Object(int size) {
        this("White", "Blue", size);
      }
      

      或者是静态工厂方法(具有Effective Java第1条中提到的“命名构造器”的优点,可以让int参数的意义自证):

      static Object createWithSize(int size) {
        return new Object ("White", "Blue", size);
      }
      

      【讨论】:

      • 如果“默认值”不依赖于使用哪个构造函数或提供的值之一,那么我将初始化成员变量,而不是需要 this(...) 调用。对于您的示例,只需 this.size = size。默认值应位于一个位置,而不是分散在其他构造函数 this() 调用中。
      • @JimGarrison 每个人都有。我习惯于编写有“一个真正的构造函数”的类,而所有其他的只是调用this(...) 的便利重载。
      • 在这种情况下,假设您有 5 个不同的构造函数都调用“1 个真正的构造函数”,那么您必须跟踪所有 5 个 this() 调用中的默认值。当默认值发生变化时,你想在 5 个地方寻找它吗?
      • @JimGarrison 还有,为什么this.foo = "defaultFoo"; this.bar = "defaultBar"; 在不分散默认值方面比this("defaultFoo", "defaultBar"); 更好?您仍然拥有该 ctor 中的默认值。也许我误解了你的意思。
      • @JimGarrison 在静态成员中定义默认值?
      猜你喜欢
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2017-09-27
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多