【问题标题】:Reusing code in overloaded constructors在重载的构造函数中重用代码
【发布时间】:2011-11-21 19:38:09
【问题描述】:

我的BigBlock 类需要一些重载的构造函数。他们都需要以相同的方式初始化相同的几个字段。

这样做的正确方法是什么?是做一个功能吗,例如Initialize在下面的例子中,做这些事情,并且让所有的构造函数调用那个函数?

public class BigBlock {
    private Thing parentThing;
    Units lengthUnit;
    LabCoordinateSystem labCoordinateSystem;

    private void Initialize(){
        lengthUnit = parentThing.getPreferredUnits(0);
        labCoordinateSystem = parentThing.getCoordinateSystem();
    }

    BigBlock(Thing myThing){
        parentThing= myThing;
        Initialize();
    }

    BigBlock(Thing myThing, double x, double y, double z){
        parentThing= myThing;
        Initialize();
        // more code involving x, y, z
    }

    // a few more constructors

}

【问题讨论】:

    标签: java oop constructor


    【解决方案1】:

    通常最好将所有构造函数链接到包含最多信息的单个构造函数,例如

    BigBlock(Thing myThing) {
        this(myThing, 0, 0, 0); // Assuming 0 is the default value for x, y and z
    }
    

    如果有不同的方法来调用构造函数而有效地表示相同信息的子集,这会变得有点奇怪 - 但在这一点上,我会说无论如何都有设计气味。

    请注意,当您在单个构造函数中获得所有真正的逻辑时,您根本不需要您的 Initialize 方法(应该是 initialize 以遵循 Java 命名约定,顺便说一句) - 这可能您可以将以前无法完成的字段设置为最终字段。

    【讨论】:

    • 有趣。为什么不采取其他方式呢?直观地说,我会从特定构造函数(即BigBlock(Thing myThing, double x, double y, double z){ this(myThing); // etc })调用通用构造函数,这就是其他两个答案所暗示的。但是您可能有理由更喜欢这种方式?
    • @Jean-FrançoisCorbett:它将所有初始化逻辑放在一个地方。另请记住,您不能链接到多个构造函数 - 如果您有一个构造函数只使用 Foo,一个构造函数只使用 Bar,而一个构造函数同时使用两者,我的方法有效 - 另一个没有't,因为您将无法从“完整”构造函数中调用 both 构造函数。
    • 请注意,我将BigBlock(Thing myThing, double x, double y, double z) 视为更 general 构造函数,因为它允许 any 类型的初始化。 BigBlock(Thing) 构造函数是一个更特定的构造函数,因为它允许您使用 x、y 和 z 的默认值进行初始化。
    【解决方案2】:

    只需重用您当前的构造函数。让所有其他构造函数调用初始化所有必需值的构造函数。

    BigBlock(Thing myThing){
        parentThing = myThing;
        lengthUnit = parentThing.getPreferredUnits(0);
        labCoordinateSystem = parentThing.getCoordinateSystem();
    
    }
    
    BigBlock(Thing myThing, double x, double y, double z){
        this(myThing);
        // more code involving x, y, z
    }
    

    如果xyz 需要成为初始化的一部分,则BigBlock(Thing myThing) 应使用默认值调用BigBlock(Thing myThing, double x, double y, double z)

    【讨论】:

      【解决方案3】:

      否 - 您可以使用 this 从构造函数调用其他构造函数。

      BigBlock(Thing myThing) {
        this(myThing,0,0,0); // Pass default values for other constructors
      }
      

      【讨论】:

        【解决方案4】:

        几乎与往常一样,“哪种方式是……的正确/最佳方式”的答案是“取决于”。

        如果Initialize 背后的逻辑与对象创建特别相关,并且Thing 在所有创建方面都很常见,那么您可以通过在最简单的构造函数中插入该行为并在其他所有构造函数中使用它来对其进行建模。这会将初始化行为的这种用法集中在一个地方。

        BigBlock(Thing myThing){
            parentThing= myThing;
            Initialize();
        }
        
        BigBlock(Thing myThing, double x, double y, double z){
            this(myThing);
            // more code involving x, y, z
        }
        

        在其他情况下,将Initialize 作为单独的方法可能会很有用。例如,如果initialize 做了一些可重用的逻辑,比如对对象进行“重置”,您可能会在与创建对象不同的时刻调用。

        【讨论】:

          猜你喜欢
          • 2010-09-27
          • 2017-01-10
          • 2015-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多