2015-02-19 23 views
7

Przykład:Java: rekurencja ciągu głównego klasy zwraca podklasa-metoda zamiast własnej metody

class MainClass { 
    public doIt() { 
     ... 
     else doIt(); 
    } 
} 

class SubClass extends MainClass { 
    @Override 
    public doIt() { 
     super.doIt(); 
     ... 
    } 
} 

Teraz problem jest:

  • nazywam SubClass.doIt()
  • MainClass .doIt() jest nazywane
  • MainClass.doIt() wywołuje rekursję doIt()
    Ale: wywoływana jest metoda SubClass.doIt() zamiast MainClass.doIt()

To jest bardzo dziwne zachowanie i problemy są programowane! Próbowałem wywołać rekursję za pomocą this.doIt(), ale to nie pomogło. Ktoś ma pomysł?

Dzięki za odpowiedzi, ten problem został rozwiązany.

+3

To jest polimorfizm dla ciebie. – GriffeyDog

+0

"* To bardzo dziwne zachowanie *" niezupełnie, "else doIt()' jest takie samo jak 'else this.doIt()' ale 'this' odnosi się do bieżącej instancji, a dzięki dynamicznemu wiązaniu (mechanizm polimorfizmów) kod od metody klasy najbliższej bieżącego typu 'this' jest wywoływana. Ponieważ najbliższą klasą do 'SubClass' zawierającą' doIt' jest 'SubClass', ten kod jest wywoływany. – Pshemo

+0

To rzekome zachowanie. –

Odpowiedz

7

To jest przypuszczalne zachowanie, nie ustawiając metody final, co oznacza, że ​​może to być override n, więc musisz zawsze brać pod uwagę, że ktoś może to zrobić. Wezwanie do tej metody nigdy nie są gwarantowane, aby być metodą na tym poziomie.

Można jednak rozwiązać ten problem elegancko, stosując metodę (protected) final:

class MainClass { 

    protected final void innerDoIt() { //final: so no @Override 
     ... 
     else innerDoIt(); 
    } 

    public void doIt() { 
     innerDoIt(); 
    } 

} 

, a następnie:

class SubClass extends MainClass { 

    @Override 
    public doIt() { 
     super.doIt(); 
     ... 
    } 
} 

final, zapewnia, metoda ta nie może być nadpisane. Tak więc w tym momencie masz umowę (gwarancję), że metoda innerDoIt jest rzeczywiście metodą, którą Twoim zdaniem jest.

Tak więc w przypadku nie należy dzwonić do operatora, aby uzyskać poprawkę, wystarczy zabezpieczyć go w innej metodzie final. Dzięki temu protected, metoda ta może być również wywołana przez SubClass.

+0

ok nie wiedziałem, że cud, że wszystkie moje rzeczy biegną do teraz: p - wielkie dzięki – Sneedlewoods

1
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"); 
     } 
    } 
} 

W tym przykładzie zarówno b i a są instancjami klasy B, tak jak zapewne oczekiwać, a.doIt() i b.doIt() wyświetli ten sam wynik.

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 

Po wywołaniu doIt(), jesteś niejawnie wywołanie this.doIt() i this jest instancją klasy B. Nie ma żadnej składni, aby zrobić to, co chcesz, bez oddzielania treści od doIt() (patrz odpowiedź CommuSoft).