Java, вызов переопределенного метода неявно - PullRequest
2 голосов
/ 03 октября 2009

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

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

Ответы [ 3 ]

8 голосов
/ 03 октября 2009

Вызывать не финальные методы в конструкторе, как правило, плохая идея - по крайней мере, я бы посоветовал вам документировать это в значительной степени . Имейте в виду, что когда вызывается функция f (), конструктор C не вызывается, равно как и инициализаторы переменных. Объект инициализируется только наполовину, поэтому методы должны быть написаны очень тщательно.

Нет способа неявно вызвать super.f(), хотя в обычной Java. Учитывая большие предупреждения, которые я бы поставил вокруг этого кода, одно утверждение далеко от конца света:)

Если вы хотите убедиться, что он вызывается, вы всегда можете проверить результаты A.f() в конструкторе А сразу после вызова - это проверит, что вызов достиг верхнего уровня.

4 голосов
/ 03 октября 2009

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

1 голос
/ 03 октября 2009

Насколько я знаю, нет способа сделать это. AspectJ может сделать что-то похожее на это, но тогда вам придется пометить это аннотацией, я полагаю, что это едва ли меньше работы, чем просто вызов super.f(). Вы должны указать, что метод суперкласса вызывается, потому что вам нужно иметь возможность принимать это решение для каждого подкласса отдельно - в противном случае у вас может быть подкласс, который вообще не хочет делегировать что-либо суперклассу - так по умолчанию вы просто вводите код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...