开发者

Reusing code in overloaded constructors

开发者 https://www.devze.com 2023-04-06 04:12 出处:网络
My BigBlock class needs a few overloaded constructors. All of them need to initializethe same few fields in the same way.

My BigBlock class needs a few overloaded constructors. All of them need to initialize the same few fields in the same way.

What is the proper way to do this? Is it to make a function, e.g. Initialize in the example below, that does these things, and have all constructors call that function?

public class BigBlock {
    private Thing parentThing;
    Units l开发者_JS百科engthUnit;
    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

}


Typically it's best to make all constructors chain to a single one which contains the most information, e.g.

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

It becomes slightly weirder if there are different ways to call the constructor which don't effectively represent subsets of the same information - but at that point I'd say there's a design smell anyway.

Note that by the time you've got all the real logic in a single constructor, you don't need your Initialize method (which should be initialize to follow Java naming conventions, btw) at all - which may also you can make fields final which previously you couldn't have done.


Just reuse your current constructor. Let every other constructor call the one that initialises all required values.

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
}

If x,y and z need to be part of the initalization, BigBlock(Thing myThing) should call BigBlock(Thing myThing, double x, double y, double z) with default values.


No - you can call other constructors from a constructor using this.

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


As almost always, the answer to 'which is the proper/best way to...' is "depends".

If the logic behind Initialize is specifically coupled to object creation, and Thing is common in all creation aspects, you could model that by inserting that behavior on the simplest constructor, and using it in every other one. That would centralize this usage of the initialisation behavior in only one place.

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

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

In other circumstances, it may be useful to have Initialize as a separate method. For instance, if initialize does some reusable logic, llike a "reset" on the object you may call in a moment different than object creation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号