Автоматический вызов метода суперкласса

#java #abstract-class #superclass

#java #наследование

Вопрос:

Рассмотрим следующий класс

 class A{
    public void init(){
        //do this first;
    }
    public void atEnd(){
        //do this after init of base class ends
    }
}

class B1 extends A{

    @Override
    public void init()
    {
        super.init();
        //do new stuff.
        //I do not want to call atEnd() method here...
    }
}
  

У меня есть несколько B1, B2,… Bn дочерних классов, которые уже разработаны. Все они расширяют класс A. Если я хочу добавить новую функциональность во все из них, лучшее место для этого — определить это в методе внутри класса A. Но условием является то, что метод всегда должен вызываться автоматически непосредственно перед завершением метода init() дочернего класса.
Один из основных способов сделать это — снова добавить вызов метода atEnd() в конце метода init() дочерних классов. Но есть ли какой-либо другой способ сделать это разумно??

Ответ №1:

Один из способов сделать это — сделать init() final и делегировать его работу второму, переопределяемому методу:

 abstract class A {
  public final void init() {
    // insert prologue here
    initImpl();
    // insert epilogue here
  }
  protected abstract void initImpl();
}

class B extends A {
  protected void initImpl() {
    // ...
  }
}
  

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

Ответ №2:

Другой мыслью было бы включить аспект. Добавьте рекомендации «до» и «после» к точечному вырезу.

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

1. Если речь идет о защите инвариантов класса, AOP был бы очень плохим решением.

2. Речь идет о «делать вещи»; инварианты не упоминаются. И я не уверен, что «очень плохой» подходит, основываясь на предоставленной информации.

Ответ №3:

Создайте init() final и предоставьте людям отдельный метод для переопределения этих init() вызовов в середине:

 class A{
    public final void init(){
        //do this first;
    }

    protected void initCore() { }

    public void atEnd(){
        //do this after init of base class ends
    }
}

class B1 extends A{

    @Override
    protected void initCore()
    {
        //do new stuff.
    }
}
  

Ответ №4:

Другие ответы являются разумными обходными путями, но для решения точного вопроса: нет, нет способа сделать это автоматически. Вы должны явно вызвать super.method() .