Java: постобработка после завершения конструктора подкласса - PullRequest
7 голосов
/ 05 мая 2011

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

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

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

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

Спасибо

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

Ответы [ 3 ]

3 голосов
/ 05 мая 2011

Если вы не можете использовать фабричный метод по прагматическим соображениям, лучшее решение, о котором я могу подумать, - это создать 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().


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

2 голосов
/ 05 мая 2011

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

Вы думали о своем дизайне и как его можно изменить? Может быть, вам нужен какой-то шаблон проектирования, такой как Factory Method, Abstract Factory, Builder?

2 голосов
/ 05 мая 2011

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

...