Java, вызов переопределенного метода неявно
Прямо сейчас в каком-то Java-коде у меня есть что-то вроде этого
class A {
void f() {
}
A() {
f();
}
}
class B extends A{
@Override
void f() {
//do some stuff
super.f();
}
}
class C extends B {
@Override
void f() {
//do some stuff
super.f();
}
}
Я хочу, чтобы f()
вызывал, а затем итерацию вверх через каждый родительский класс, запуская переопределенный f()
. Я делаю это, явно называя super.f()
, хотя я бы не хотел этого делать.
Причина, по которой я делаю это, - это пост-обработка, которая должна быть выполнена после достижения конструктора в A. И в каждом классе есть состояние, которое должно быть правильно init'd, поэтому у нас есть восходящий след f()
.
Итак, конструктор A
действительно
A() {
//init some state in a
f(); //run f(), which will depend on the previous operation
}
Если я делаю что-то вроде new C();
, я хочу вызвать C.f()
, затем B.f()
, затем A.f()
, называемый
В любом случае, если есть более разумный способ сделать это, я открыт для него.
Ответы
Ответ 1
Вызов не конечных методов в конструкторе - это, как правило, плохая идея - по крайней мере, я предлагаю вам документировать ее в значительной степени. Имейте в виду, что, когда вызывается f(), конструктор C не будет вызван - и ни один из переменных инициализаторов не будет. Объект только частично инициализирован, поэтому методы нужно будет писать очень осторожно.
Нет никакого способа неявного вызова super.f()
, хотя в обычной Java. Учитывая большие предупреждения, которые я буду использовать для этого кода, одно утверждение далеко от конца света:)
Если вы хотите проверить, что он вызвал, вы всегда можете проверить результаты A.f()
в конструкторе A сразу после вызова - это будет проверять, что вызов достиг верхнего уровня.
Ответ 2
Это может помочь вам несколько - это способ обеспечить, чтобы класс child вызывал супер; это поможет вам обнаружить ошибки разработчиков, когда разработчик дочернего класса забыл продолжить вызов цепочки на super.f():
class A {
boolean fDone;
public final void f() {
fDone = false;
doF();
if (!fDone) {
throw new IllegalStateException("super.f() was not called");
}
}
protected void doF() {
//do some operation
fDone = true;
}
}
class B extends A {
protected void doF() {
//some operation, maybe repeat this pattern of using a flag to enforce super call
super.doF();
}
}
Итак, ребенок переопределяет doF(), но требуется вызвать super.doF();
Ответ 3
Насколько я знаю, нет никакого способа сделать это. AspectJ может сделать что-то похожее на это, но тогда вам придется пометить его аннотацией, я полагаю, что вряд ли будет работать, чем просто позвонить super.f()
. Вам нужно указать, что метод суперкласса вызывается, потому что вам нужно иметь возможность принимать это решение для каждого подкласса отдельно - иначе у вас может быть подкласс, который вообще не хочет делегировать что-либо суперклассу, поэтому по умолчанию вы просто вставляете код.