Java 像这样在构造函数中调用init方法是否违反了干净代码

Java 像这样在构造函数中调用init方法是否违反了干净代码,java,oop,coding-style,Java,Oop,Coding Style,我在下面的代码中担心的是,param to构造函数实际上并没有直接映射到类的实例字段。实例字段从参数中派生值,我正在使用initalize方法。此外,我还做了一些工作,以便创建的对象可以直接在后面的代码中使用,例如调用DrawBounders()。我觉得它在做抽象意义上创建(初始化)画布的工作 我的构造函数做得太多了吗?如果我添加方法从外部显式调用构造函数中的内容,那就错了。请让我知道你的看法 public class Canvas { private int numberOfRows; pr

我在下面的代码中担心的是,param to构造函数实际上并没有直接映射到类的实例字段。实例字段从参数中派生值,我正在使用initalize方法。此外,我还做了一些工作,以便创建的对象可以直接在后面的代码中使用,例如调用DrawBounders()。我觉得它在做抽象意义上创建(初始化)画布的工作

我的构造函数做得太多了吗?如果我添加方法从外部显式调用构造函数中的内容,那就错了。请让我知道你的看法

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);
}
...
公共类画布{
私有整数行;
私有整数列;
private final List List of cells=new LinkedList();
公共画布(ParsedCells-seedPatternCells){
初始化CANVAS(种子模式细胞);
}
私有void initializecanvas(ParsedCells-seedPatternCells){
设置种子模式下的行数和列数(种子模式单元格);
绘制边界();
将seedPatternCells放置在画布上(seedPatternCells);
}
...
注:如果这看起来像个愚蠢的问题,很抱歉;我的代码将由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;
}
公共类画布{
私有整数行;
私有整数列;
private final List List of cells=new LinkedList();
私有画布(){
}
公共静态画布newInstance(ParsedCells-seedPatternCells){
画布=新画布();
canvas.setNumberOfRowsAndColumnsBasedOnSeedPatten(种子模式单元格);
canvas.drawBounders();
canvas.placeSeedPatternCellsCanvas(seedPatternCells);
返回画布;
}

< /代码> 虽然它不是最优雅的方法,但我不认为它是从OO角度来看有缺陷的。但是,如果您没有从类中的任何地方调用<代码>私下<代码>方法>代码> iITALIZECANVAs/COD>,那么您可以考虑将这三行移到构造函数本身。

< P>我看到两个潜在的问题:

  • 您在
    initializeCanvas
    中调用的方法是private还是final?如果不是,子类可能会重写它们并无意中破坏构造函数

  • 您是否在
    drawBounders
    方法中执行图形操作?构造函数最好只执行创建有效对象所需的最小操作。画布是否需要这些操作才能具有有效的初始状态


您不应该在构造函数中调用非final方法。有效的Java很好地解释了原因,但在构造函数返回之前,基本上您的对象没有处于稳定状态。如果您的构造函数调用被子类重写的方法,您可能会出现奇怪的、未定义的行为

另请参见。

视情况而定

构造函数调用私有方法并不坏,前提是该私有方法不调用可以重写的其他方法。但是,如果该方法或它调用的其中一个方法可以被重写,则可能会遇到问题。具体而言,重写方法将在重写类构造函数运行之前被调用并在初始化实例字段之前查看它们


第二个问题是,如果
initializecanvas
方法中的某些方法看起来像我的“发布”当前对象尚未完全初始化。如果应用程序是多线程的,则可能会出现问题,并可能导致其他线程看到过时的字段值。

通常,构造函数包含非平凡代码是个坏主意。通常,构造函数最多应将提供的值分配给字段。如果n对象需要复杂的初始化,该初始化应由另一个类负责(通常为a)。请参阅Miško Hevery关于此主题的精彩文章:。

如果有多个构造函数,其中某些参数是默认的或推断的,则私有init函数可能会很有用。确定所有内容后,一个私有init函数将填充对象


在一个构造函数类中,可能没有。

我看不出你的代码有任何可以争辩的错误。在这种情况下,方法是
私有的
,因此它不能被子类覆盖。我缺少什么吗?是的,你的私有方法正在调用其他方法。所有这些方法都是私有的和/或最终的吗?我几年前参加了一次工作面试几年前,他们问我一段代码出了什么问题。在提到了显而易见的问题后,我告诉他们有一个潜在的设计问题,因为根据经验,我们从不从构造函数调用私有方法。-这在半小时的讨论中升级,因为面试官根本不相信我。最后,他们没有给出答案我得到了这份工作。很明显,他是针对个人的。据采访者说:“我不懂OOP。”——)-但有一本像《有效java》这样的书的参考文献是很好的。那将是一个明显的胜利。