Повторное использование кода в перегруженных конструкторах - PullRequest
10 голосов
/ 21 сентября 2011

Моему 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

}

Ответы [ 4 ]

22 голосов
/ 21 сентября 2011

Как правило, лучше всего объединить все конструкторы в один, содержащий наибольшую информацию, например,

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

Это становится немного страннее, если есть разные способы вызова конструктора, который don 't эффективно представляет подмножества одной и той же информации, но в этот момент я бы сказал, что дизайн все равно пахнет.

Обратите внимание, что к тому времени, когда вы получите всю реальную логику в одном конструкторе,вам вообще не нужен ваш Initialize метод (который должен быть initialize для соблюдения соглашений об именах Java, кстати) - который может также , вы можете сделать поля окончательными, чего раньше вы не могли бы сделать.

3 голосов
/ 21 сентября 2011

Просто используйте ваш текущий конструктор.Пусть каждый другой конструктор вызывает тот, который инициализирует все необходимые значения.

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
}

Если x, y и z должны быть частью инициализации, BigBlock(Thing myThing) должен вызвать BigBlock(Thing myThing, double x, double y, double z) со значениями по умолчанию.

2 голосов
/ 21 сентября 2011

Нет - вы можете вызывать другие конструкторы из конструктора, используя это.

BigBlock(Thing myThing) {
  this(myThing,0,0,0); // Pass default values for other constructors
}
1 голос
/ 21 сентября 2011

Как почти всегда, ответ на вопрос «какой правильный / лучший способ ...» - «зависит».

Если логика 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 выполняет некоторую повторно используемую логику, то есть «сброс» объекта, который вы можете вызвать в момент, отличный от создания объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...