Java: последующая обработка после завершения конструктора подкласса

#java #inheritance #constructor #subclass

#java #наследование #конструктор #подкласс

Вопрос:

Я хочу определить некоторое общее поведение после конструирования для группы классов. Когда у вас есть общие модели поведения в разных классах, Java сообщает нам извлечь их в родительский класс.

Концептуально, мы говорим, что для объектов этого типа (и его подклассов) имеет смысл выполнить некоторую постобработку после его создания;

На практике это сложно сделать. Очевидно, что вы не можете поместить это в конструктор родительского класса, потому что родительский конструктор вызывается перед конструктором подкласса. Я мог бы написать метод postInit() в родительском классе и потребовать, чтобы все подклассы вызывали его в качестве последнего оператора в своих конструкторах, но это кажется не очень чистым, поскольку нет способа обеспечить его соблюдение, и люди забывают.

Может быть, есть какая-то языковая конструкция, о которой я не знаю, которая может решить мою проблему?

Спасибо

Просто немного больше информации о требовании. Фабричные методы и т.д., Которые предлагаются многими ответами (за которые я проголосовал) ниже, — все это хорошие идеи, но на самом деле у меня нет такой роскоши. Фактическая ситуация такова, у меня есть этот родительский класс, который расширен парой десятков подклассов, которые, в свою очередь, используются во многих других местах. Поэтому о перепроектировании способа использования этих подклассов не может быть и речи, а изменение всех подклассов практически возможно. В идеале мне просто нужно изменить родительский класс, вот о чем я спрашиваю.

Ответ №1:

Если вы не можете использовать фабричный метод по прагматическим причинам, лучшее решение, которое я могу придумать, это создать protected final метод в корневом классе, который выполняет постобработку, и добавить вызов метода к каждому конечному классу; например

 public abstract class Root {
    ...
    protected final void finishInit() {
        // Do post-processing
    }
}

public abstract class Intermediate {
    ...
    protected Intermediate(...) {
        super(...);
        ...
        // don't call finishInit();
    }
    ...
}

public class Leaf {
    ...
    public Leaf(...) {
       super(...);
       ...
       finishInit();
    }
    ...
}
  

Если Intermediate это не abstract так, то вам нужен отдельный общедоступный конструктор для создания экземпляров, которые вызываются finishInit() в конце.


Все это немного неуклюже, но это штраф, который вам придется заплатить, если вы не можете / не будете рефакторинговать свой код для использования заводских методов.

Комментарии:

1. Это делает … фабричные методы 🙂

2. В нем также есть IDE, которые упрощают рефакторинг вашего кода для исправления (некоторых) ошибок проектирования. 🙂 🙂

Ответ №2:

Одним из решений является отсутствие какого-либо общедоступного ctor. У вас может быть фабричный метод, который завершает инициализацию перед возвратом объекта вызывающей стороне.

Ответ №3:

Что ж, самое простое решение — добавить шаблон для этой иерархии классов в IDE.

Думали ли вы о своем дизайне и о том, как его можно изменить? Может быть, вам нужен какой-то шаблон проектирования, например, фабричный метод, абстрактная фабрика, конструктор?

Комментарии:

1. 1 для заводского класса / метода он может вызывать finishInit() после создания подкласса.