Java: рекурсия внутри основного класса вызывает метод subclass вместо своего собственного метода
Пример:
class MainClass {
public doIt() {
...
else doIt();
}
}
class SubClass extends MainClass {
@Override
public doIt() {
super.doIt();
...
}
}
Теперь проблема заключается в следующем:
- Я вызываю SubClass.doIt ()
- MainClass.doIt() вызывается
- MainClass.doIt() делает рекурсию, вызывая doIt ()
Но: SubClass.doIt () вызывается вместо MainClass.doIt()
Это очень странное поведение и проблемы запрограммированы! Я пытался вызвать рекурсию с помощью this.doIt (), но это не помогло. У кого-то есть идея?
Большое спасибо за ваши ответы, эта проблема решена.
2 ответа
Это предполагаемое поведение, не устанавливая метод final
это означает, что это может быть override
п, так что вы всегда должны учитывать, что кто-то может сделать это. Призывы к этому методу никогда не гарантированно относятся к методу на этом уровне.
Однако вы можете решить эту проблему элегантно, используя (protected
) final
метод:
class MainClass {
protected final void innerDoIt () { //final: so no @Override
...
else innerDoIt();
}
public void doIt() {
innerDoIt();
}
}
А потом:
class SubClass extends MainClass {
@Override
public doIt() {
super.doIt();
...
}
}
final
гарантирует, что метод не может быть переопределен. Таким образом, в этот момент у вас есть контракт (гарантия), что innerDoIt
Метод действительно innerDoIt
метод вы думаете, что это так.
Так что, если вы не хотите, чтобы вызывающий абонент был переопределен, просто хеджируйте его в другой final
метод. Делая это protected
этот метод также может быть вызван SubClass
,
public class Main {
public static void main(String[] args) {
B b = new B();
b.doIt();
System.out.println();
A a = new B();
a.doIt();
}
public static class A{
boolean check=false;
public void doIt(){
System.out.println("A start");
if(check){
}
else{
check = true;
doIt();
}
System.out.println("A end");
}
}
public static class B extends A{
@Override
public void doIt() {
System.out.println("B start");
super.doIt();
System.out.println("B end");
}
}
}
В этом примере оба b
а также a
являются экземплярами класса B
так что, как вы, вероятно, ожидаете, a.doIt() и b.doIt() будут выводить один и тот же результат.
B start
A start
B start
A start
A end
B end
A end
B end
B start
A start
B start
A start
A end
B end
A end
B end
Когда вы звоните doIt()
Вы неявно звоните this.doIt()
, а также this
это экземпляр класса B
, Там нет синтаксиса, чтобы делать то, что вы хотите сделать, не разделяя содержимое doIt()
(см. ответ CommuSoft)