Является ли нарушение чистым кодом вызовом метода init в конструкторе, как это
Моя озабоченность в приведенном ниже коде заключается в том, что параметр для конструктора фактически не сопоставляется непосредственно с полями экземпляра класса. Поля экземпляра извлекают значение из параметра и для которого я использую метод 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.: Извините, если это выглядит глупым вопросом; мой код будет рассмотрен гуру ООП, и я просто волнуюсь: -0
EDIT:
Я прочитал некоторые соображения о том, что методы 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;
}
Ответы
Ответ 1
Как правило, плохая идея для конструктора содержать нетривиальный код. Как правило, конструкторы должны в большинстве случаев назначать заданные значения полям. Если объект требует сложной инициализации, эта инициализация должна отвечать другому классу (обычно factory). См. Miško Hevery отличная рецензия на эту тему: Недостаток: конструктор действительно работает.
Ответ 2
Вы никогда не должны вызывать неконкретные методы в конструкторе. Эффективная Java хорошо описывает, почему, но в основном ваш объект не находится в стабильном состоянии до того, как возвращается конструктор. Если ваш конструктор вызывает методы, которые переопределяются подклассом, вы можете получить странное поведение undefined.
Также см. этот ответ.
Ответ 3
Хотя это не самый изящный способ сделать это, я не вижу в этом недостатка с точки зрения ОО. Однако, если вы не вызываете метод private
initalizeCanvas
из любого другого места в классе, вы можете рассмотреть возможность перемещения этих трех строк к самому конструктору.
Ответ 4
Я вижу две потенциальные проблемы:
-
Являются ли методы, которые вы вызываете в initializeCanvas
частном или конечном? Если это не так, то подкласс может переопределить их и невольно разбить ваш конструктор.
-
Выполняете ли вы графические операции в методе drawBoundaries
? Это хорошая практика для конструктора, чтобы сделать только минимум, необходимый для создания действительного объекта. Являются ли эти операции необходимыми для того, чтобы холст имел правильное начальное состояние?
Ответ 5
Это зависит.
Неплохо, чтобы конструктор вызывал частный метод, при условии, что частный метод не вызывает другие методы, которые можно было бы переопределить. Однако, если метод или один из методов, которые он вызывает, можно переопределить, вы можете столкнуться с проблемами. В частности, метод переопределения будет вызываться до запуска конструктора переопределяющих классов и будет видеть поля экземпляра до их инициализации.
Вторая проблема, если некоторые из методов в вашем методе initalizeCanvas
выглядят так, как будто они "публиковали" текущий объект до его полной инициализации. Это потенциально проблематично, если приложение многопоточное и может привести к тому, что другие потоки будут видеть значения устаревших полей.
Ответ 6
Частная функция инициализации может быть полезна, если у вас есть несколько конструкторов, где некоторые параметры дефолт или выводятся по умолчанию. После того, как все определено, одна частная функция инициализации заполняет объект.
В классе с одним конструктором, вероятно, нет.