#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() после создания подкласса.