Перегрузка конструктора в Java - лучшая практика
Есть несколько тем, похожих на эту, но я не смог найти одну с достаточным ответом.
Я хотел бы знать, что является лучшей практикой для перегрузки конструктора в Java. У меня уже есть свои мысли по этому вопросу, но я хотел бы услышать больше советов.
Я имею в виду как перегрузку конструктора в простом классе, так и перегрузку конструктора при наследовании уже перегруженного класса (то есть базовый класс имеет перегруженные конструкторы).
Спасибо:)
5 ответов
Пока нет никаких "официальных указаний", я следую принципам KISS и DRY. Сделайте перегруженные конструкторы настолько простыми, насколько это возможно, и самый простой способ заключается в том, что они только вызывают это (...). Таким образом, вам нужно только один раз проверить и обработать параметры.
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
}
}
С точки зрения модульного тестирования, будет легко протестировать класс, так как вы можете добавить в него ресурсы. Если у класса много ресурсов (или коллаборационистов, как его называют некоторые вундеркинды), рассмотрим одну из следующих двух вещей:
Сделать класс параметров
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
класс, что они используются одинаково.
Я думаю, что лучше всего иметь один первичный конструктор, на который ссылаются перегруженные конструкторы, вызывая this()
с соответствующими параметрами по умолчанию. Причиной этого является то, что это делает намного более ясным, каково состояние объекта: действительно, вы можете думать о первичном конструкторе как о единственном реальном конструкторе, другие просто делегируют ему
Одним из примеров этого может быть JTable
- основной конструктор принимает TableModel
(плюс столбец и модели выбора) и другие конструкторы вызывают этот первичный конструктор.
Для подклассов, где у суперкласса уже есть перегруженные конструкторы, я бы предположил, что разумно рассматривать любой из конструкторов родительского класса как первичный, и думаю, что вполне законно не иметь единственного первичного конструктора. Например, при расширении Exception
Я часто предоставляю 3 конструктора, один из которых занимает всего String
сообщение, один принимая Throwable
причина, а другой принимает оба. Каждый из этих конструкторов вызывает super
непосредственно.
Если у вас очень сложный класс с большим количеством опций, для которых допустимы только некоторые комбинации, подумайте об использовании Builder. Работает очень хорошо как по кодам, так и по логике.
Builder - это вложенный класс с методами, предназначенными только для установки полей, и тогда конструктор ComplexClass принимает в качестве аргумента только такой Builder.
Редактировать: конструктор ComplexClass может гарантировать, что состояние в Builder является действительным. Это очень сложно сделать, если вы просто используете сеттеры на ComplexClass.
Это действительно зависит от вида классов, поскольку не все классы созданы равными.
В качестве общего руководства я бы предложил 2 варианта:
- Для классов value & immutable (Exception, Integer, DTO и т. Д.) Используйте один первичный конструктор, как предложено в ответе выше.
- Для всего остального (сессионные компоненты, сервисы, изменяемые объекты, сущности JPA & JAXB и т. Д.) Используйте конструктор по умолчанию только с разумными значениями по умолчанию для всех свойств, поэтому его можно использовать без дополнительной настройки.
Ну, вот пример для перегруженных конструкторов.
public class Employee
{
private String name;
private int age;
public Employee()
{
System.out.println("We are inside Employee() constructor");
}
public Employee(String name)
{
System.out.println("We are inside Employee(String name) constructor");
this.name = name;
}
public Employee(String name, int age)
{
System.out.println("We are inside Employee(String name, int age) constructor");
this.name = name;
this.age = age;
}
public Employee(int age)
{
System.out.println("We are inside Employee(int age) constructor");
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
}
В приведенном выше примере вы можете увидеть перегруженные конструкторы. Имя конструкторов одинаковое, но каждый из них имеет разные параметры.
Вот некоторые ресурсы, которые проливают больше света на перегрузку конструктора в Java,
Перегрузка конструктора похожа на перегрузку метода. Конструкторы можно перегружать для создания объектов разными способами.
Компилятор различает конструкторы в зависимости от количества аргументов, присутствующих в конструкторе, и других параметров, таких как порядок, в котором аргументы передаются.
Для получения дополнительных сведений о конструкторе java посетите https://tecloger.com/constructor-in-java/