2009-04-10 10 views
5

Mam następujących klas:Czy super klasa nie wywołuje metody nadpisanej?

class foo { 
    public void a() { 
     print("a"); 
    } 
    public void b() { 
     a(); 
    } 
} 

class bar extends foo { 
    public void a() { 
     print("overwritten a"); 
    } 
} 

Kiedy teraz nazywają bar.b() Chcę, aby wywołać metodę zastąpiona a() w foo. Jednak drukuje "a".

+3

Ułagodzenie dydaktyki: To się nazywa "nadpisywanie", a nie "nadpisywanie". – erickson

+0

Kod, który napisałeś, powinien działać zgodnie z twoimi oczekiwaniami - wiele z poniższych odpowiedzi sugeruje uzyskanie wyniku, który właśnie wykonujesz, i musisz zrobić coś innego w swoim kodzie, którego tutaj nie pokazujesz. – Eborbob

Odpowiedz

7

Kiedy uruchomić następujące:

public class Program { 
    public static void main(String[] args) { 
     bar b = new bar(); 
     b.b(); 
    } 
} 

class foo { 
    public void a() { 
     System.out.printf("a"); 
    } 
    public void b() { 
     a(); 
    } 
} 

class bar extends foo { 
    public void a() { 
     System.out.printf("overwritten a"); 
    } 
} 

pojawia się następujący komunikat:

overwritten a 

która jest co by się spodziewać, aby zobaczyć.

+0

Pokonałeś mnie o minutę. Otrzymuję to samo wyjście. – Eddie

+0

Być może pobił cię w publikowaniu, w przeciwnym razie, wydaje mi się, że otrzymaliśmy tę metodę wyjściową, zanim to pytanie zostanie opublikowane. –

9

Możliwe, że próbujesz użyć metod statycznych, które nie zadziałają, ponieważ nie zostaną zastąpione.

Dobrym sposobem sprawdzenia jest dodanie @Override adnotacji do bar.a() i sprawdzić, czy kompilator daje błąd, że() nie jest faktycznie overidding nic

+2

+1 dla zalecenia @Override – Rob

0

można mylić jeśli pochodzisz z języka C# lub innego języka, w którym musisz jawnie deklarować funkcje wirtualne i/lub funkcje nadpisujące.

W Javie wszystkie funkcje instancji są wirtualne i mogą być nadpisane - chyba że są zadeklarowane jako prywatne i/lub ostateczne.

Nie trzeba określać nowej adnotacji @Override, aby to zrobić, dodając adnotację tylko określa, że ​​zamiar ma przesłonić i spowoduje ostrzeżenie lub błąd, jeśli nie jest to przesłonięcie. (Jeśli przypadkowo błędnie wpisałeś nazwę metody na przykład).

Przykład Andrew pokazuje, jak to powinno działać.

10

Czy Twoje dwie klasy znajdują się w różnych pakietach? A czy twoje metody klasy foo są zadeklarowane jako publiczne, chronione, prywatne lub pakietowe? Oczywiście, jeśli są prywatne, to nie zadziała. Być może mniej oczywiste jest to, że jeśli są one pakietami lokalnymi (tj. Bez zakresu publicznego/chronionego/prywatnego), wówczas można je tylko zastąpić, jeśli są w tym samym pakiecie co oryginalna klasa.

Na przykład:

 
package original; 
public class Foo { 
    void a() { System.out.println("A"); } 
    public void b() { a(); } 
} 

package another; 
public class Bar extends original.Foo { 
    void a() { System.out.println("Overwritten A"); } 
} 

package another; 
public class Program { 
    public static void main(String[] args) { 
    Bar bar = new Bar(); 
    bar.b(); 
    } 
} 

W tym przypadku, można jeszcze dostać 'A'. Jeśli zadeklarujesz oryginalną metodę() w Foo publicznym lub chronionym, uzyskasz oczekiwany efekt.

+2

To był mój problem; zmiana metody supertype na protected naprawiła to. Czego nie dostaję, to dlaczego tag @Override w metodzie podtypu nie sprawił, że kompilator dostarczy mi komunikat o błędzie, jeśli nie zadziałał. – shieldgenerator7

0

Z pierwszej ręki:

http://download.oracle.com/javase/tutorial/java/IandI/override.html

„Wersja zastąpionej metody, która zostanie wywołany jest jeden w podklasie Wersja ukrytej metody, która zostanie wywołany zależy od tego, czy jest ona wywoływana. z nadklasy lub podklasy. "

Więc jeśli obie są metodami statycznymi i wywołujesz metodę z super klasy, wywoływana jest metoda super klasy, a nie metoda podklasy. Tak naprawdę, nie ma nadpisywania.

-1

Podczas pracy nad programem Android miałem ten sam problem na moich zajęciach Java. Okazało się, że problemu nie było w klasach, ale w sposobie, w jaki system operacyjny Android przetwarza dane wyjściowe.

na przykład, jeśli dane wyjściowe zostały zaprogramowane w metodzie onCreate() w klasie nadrzędnej, systemowi Android nie udało się poprawnie pobrać wyników zastąpionych metod z klas potomnych poza pierwszymi potomkami. Szczerze mówiąc nie rozumiem całego porządku wywoływania metod.

Aby rozwiązać problem, po prostu zaprogramowałem wyjście w onResume() i teraz wygląda na to, że działa dobrze.

Powiązane problemy