Конструктор, перегружающийся в Java - лучшая практика

Если вы используете GitHub и еще не отправили коммит, GitHub Desktop легко решает эту проблему:

  1. Выберите Репозиторий -> Отменить самый последний коммит
  2. Отмените выбор файл, который вы по ошибке добавили. Ваше предыдущее сообщение будет уже в диалоговом окне.
  3. Нажмите кнопку подтверждения!
105
задан Eyal Roth 25 July 2009 в 14:51
поделиться

4 ответа

Я думаю, что лучше всего иметь единственный первичный конструктор , на который ссылаются перегруженные конструкторы, вызывая this () с соответствующими значениями параметров по умолчанию. . Причина этого в том, что он делает более ясным, что такое сконструированное состояние объекта - на самом деле вы можете думать о первичном конструкторе как о единственном реальном конструкторе , а остальные просто делегировать ему

Одним из примеров этого может быть JTable - первичный конструктор принимает TableModel (плюс модели столбцов и выбора), а другие конструкторы вызывают этот первичный конструктор.

] Для подклассов , в которых суперкласс уже имеет перегруженные конструкторы , я бы склонен предположить, что разумно рассматривать любой из родительских классов » s как первичный и считаю совершенно законным отсутствие единственного первичного конструктора. Например, при расширении исключения Exception я часто предоставляю 3 конструктора, один из которых принимает только сообщение String , один принимает причину Throwable , а другой принимает оба. Каждый из этих конструкторов напрямую вызывает super .

73
ответ дан 24 November 2019 в 03:57
поделиться

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

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


Изменить: конструктор ComplexClass может гарантировать, что состояние в Builder является допустимым. Это очень сложно сделать, если вы просто используете сеттеры для ComplexClass.

6
ответ дан 24 November 2019 в 03:57
поделиться

Это действительно зависит от типа классов, поскольку не все классы созданы равными.

В качестве общего правила я бы предложил 2 варианта:

  • Для значение и неизменяемый ] классы (Exception, Integer, DTO и т. д.) используют единственный первичный конструктор , как предложено в ответе
  • выше. Для всего остального (сессионные компоненты, службы, изменяемые объекты, сущности JPA и JAXB и т.д.) используйте только конструктор по умолчанию с разумными значениями по умолчанию для всех свойств, поэтому его можно использовать без дополнительной настройки
2
ответ дан 24 November 2019 в 03:57
поделиться

Хотя нет никаких «официальных рекомендаций», я следую принципу KISS и DRY. Сделайте перегруженные конструкторы настолько простыми, насколько это возможно, и самый простой способ - они будут вызывать только this (...). Таким образом, вам нужно только один раз проверить и обработать параметры.

public class Simple {

    public Simple() {
        this(null);
    }

    public Simple(Resource r) {
        this(r, null);
    }

    public Simple(Resource r1, Resource r2) {
        // Guard statements, initialize resources or throw exceptions if
        // the resources are wrong
        if (r1 == null) {
            r1 = new Resource();
        }
        if (r2 == null) {
            r2 = new Resource();
        }

        // do whatever with resources
    }

}

С точки зрения модульного тестирования, будет легко протестировать класс, поскольку вы можете вложить в него ресурсы. Если у класса много ресурсов (или соавторов, как его называют некоторые специалисты по OO), рассмотрите одну из этих двух вещей:

Создайте класс параметров

public class SimpleParams {
    Resource r1;
    Resource r2;
    // Imagine there are setters and getters here but I'm too lazy 
    // to write it out. you can make it the parameter class 
    // "immutable" if you don't have setters and only set the 
    // resources through the SimpleParams constructor
}

Конструктору в Simple нужно только либо разделить SimpleParams параметр:

public Simple(SimpleParams params) {
    this(params.getR1(), params.getR2());
}

… или сделайте SimpleParams атрибутом:

public Simple(Resource r1, Resource r2) {
    this(new SimpleParams(r1, r2));
}

public Simple(SimpleParams params) {
    this.params = params;
}

Создайте фабричный класс

Создайте фабричный класс, который инициализирует ресурсы для вас, что является благоприятным, если инициализация ресурсов является немного сложно:

public interface ResourceFactory {
    public Resource createR1();
    public Resource createR2();
}

Конструктор затем создается так же, как и с классом параметров:

public Simple(ResourceFactory factory) {
    this(factory.createR1(), factory.createR2());
} 

Сделайте комбинацию обоих

Да ... вы можете смешивать и сочетать оба способа в зависимости от того, что для вас проще в то время. Классы параметров и простые фабричные классы - это почти одно и то же, учитывая класс Simple , что они используются одинаково.

167
ответ дан 24 November 2019 в 03:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: