我在下面的代码中担心的是构造函数的参数实际上并没有直接映射到类的实例字段。实例字段从参数中获取值,并且我正在使用initalize方法。此外,我做了一些事情,以便创建的对象可以直接在后面的代码中使用,例如调用drawBoundaries()。我觉得它是在抽象意义上创建(初始化)Canvas的意思。
我的构造函数做得太多了吗?如果我添加方法从外部显式调用构造函数中的东西,那就错了。请让我知道您的观点。
public class Canvas {
private int numberOfRows;
private int numberOfColumns;
private final List<Cell> listOfCells = new LinkedList<Cell>();
public Canvas(ParsedCells seedPatternCells) {
initalizeCanvas(seedPatternCells);
}
private void initalizeCanvas(ParsedCells seedPatternCells) {
setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells);
drawBoundaries();
placeSeedPatternCellsOnCanvas(seedPatternCells);
}
...
P.S。:对不起,如果这看起来像一个愚蠢的问题;我的代码将由OOP大师审核,我只是担心:-0
编辑:
我读到了一些关于initalizeCanvas()被覆盖的方法的担忧 - 幸运的是这些方法是私有的,不会调用任何其他方法。
无论如何,经过对网络的进一步研究,我开始喜欢这个...我希望你们同意!! ??
public class Canvas {
private int numberOfRows;
private int numberOfColumns;
private final List<Cell> listOfCells = new LinkedList<Cell>();
private Canvas() {
}
public static Canvas newInstance(ParsedCells seedPatternCells) {
Canvas canvas = new Canvas();
canvas.setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells);
canvas.drawBoundaries();
canvas.placeSeedPatternCellsOnCanvas(seedPatternCells);
return canvas;
}
答案 0 :(得分:11)
构造函数包含非平凡代码通常是一个坏主意。通常,构造函数最多应将提供的值分配给字段。如果对象需要复杂的初始化,那么初始化应该是另一个类(通常是factory)的责任。请参阅MiškoHevery关于此主题的精彩文章:Flaw: Constructor does Real Work。
答案 1 :(得分:2)
你永远不应该在构造函数中调用非final方法。 Effective Java 很好地解释了原因,但基本上你的对象在构造函数返回之前并没有处于稳定状态。如果构造函数调用被子类覆盖的方法,则可能会出现奇怪的,未定义的行为。
另见this answer。
答案 2 :(得分:1)
虽然它不是最优雅的方式,但我认为从OO的角度来看它并没有什么缺陷。但是,如果您没有从类中的任何其他位置调用private
方法initalizeCanvas
,那么您可以考虑将这三行移动到构造函数本身。
答案 3 :(得分:0)
我发现了两个潜在的问题:
您在initializeCanvas
中调用的方法是私有的还是最终的?如果不是,子类可能会覆盖它们,并且无意中破坏了构造函数。
您是否使用drawBoundaries
方法进行图形操作?构造函数只需要创建有效对象所需的最小值,这是一种很好的做法。画布是否必须具有有效的初始状态?
答案 4 :(得分:0)
取决于。
构造函数调用私有方法并不坏,只要私有方法不调用可以被覆盖的其他方法。但是,如果可以覆盖它调用的方法或其中一个方法,则可能会遇到麻烦。具体来说,覆盖方法将在覆盖类构造函数运行之前调用,并在初始化之前看到实例字段。
第二个问题,如果initalizeCanvas
方法中的某些方法看起来像我们在完全初始化之前“发布”当前对象。如果应用程序是多线程的,则可能会出现问题,并且可能导致其他线程看到陈旧的字段值。
答案 5 :(得分:0)
如果您有多个构造函数,其中某些参数是默认的或推断的,则私有init函数可能非常有用。确定所有内容后,一个私有init函数会填充该对象。
在一个构造函数类中,可能不是。