2009-04-10 3 views
5

У меня есть следующие классы:Не супер класс не вызывает переопределенный метод?

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

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

Когда я теперь называю bar.b() Я хочу, чтобы вызвать перекрытый метод а() в обув. Однако он печатает «a».

+3

Простите дидактику: она называется «переопределяющей», а не «переписывающей». – erickson

+0

Код, который вы написали, должен работать так, как вы ожидаете - так как многие из приведенных ниже ответов предлагают получить результат, который вы получаете, вы должны делать что-то еще в своем коде, который вы здесь не показываете. – Eborbob

ответ

7

Когда я запускаю следующее:

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

я получаю следующий результат:

overwritten a 

, который является тем, что я ожидал увидеть.

+0

Ты избил меня на одну минуту. Я получаю тот же результат. – Eddie

+0

Может быть, он избил вас в публикации, иначе, я считаю, мы получили этот выход, прежде чем этот вопрос будет опубликован. –

1

Являются ли методы определенными как статические? Это единственный способ получить результат. Я нашел хорошее объяснение об этом здесь: http://faq.javaranch.com/view?OverridingVsHiding

9

Возможно, вы пытаетесь использовать статические методы, которые не будут работать, поскольку они не будут переопределены.

Хороший способ проверки заключается в добавлении @Override аннотации к bar.a() и посмотреть, если компилятор выдаст ошибку, что() на самом деле не overidding что-нибудь

+2

+1 для рекомендации @Override – Rob

0

Вы можете запутаться, если вы исходите из C# или другого языка, где вы должны явно объявлять виртуальные функции и/или переопределять функции.

В Java все функции экземпляра являются виртуальными и могут быть переопределены - если они не объявлены как закрытые и/или окончательные.

Нет необходимости указывать новую аннотацию @Override для этого, добавление аннотации просто указывает, что ваше намерение переопределить и вызовет предупреждение или ошибку, если это не переопределение. (Если вы случайно набрали имя метода, например).

Пример Андрея показывает, как это должно работать.

10

Являются ли ваши два класса в разных пакетах? И являются ли ваши методы класса foo общедоступными, защищенными или частными или локальными пакетами? Очевидно, что если они частные, это не сработает. Возможно, менее очевидно, что если они являются локальными пакетами (то есть нет открытой/защищенной/частной области), тогда вы можете переопределить их только в том случае, если вы находитесь в том же пакете, что и исходный класс.

Например:

 
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(); 
    } 
} 

В этом случае, вы все равно получите 'A'. Если вы объявите оригинальный метод a() в Foo public или protected, вы получите ожидаемый результат.

+2

Это была моя проблема; изменение метода супертипа на защищенное исправление. Я не понимаю, почему тег @Override в методе подтипа не заставил компилятор дать мне сообщение об ошибке, если он не будет работать. – shieldgenerator7

0

Из первоисточника:

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

«Версия переопределенном метод, который вызывается, это один в подклассе версия скрытого метода, который вызывается, зависит от того, вызывается. из суперкласса или подкласса ».

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

-1

Когда я работал над программой для Android, у меня была такая же проблема на моих Java-классах. Оказалось, что проблема не в классах, а в том, как инфраструктура Android обрабатывает экранный вывод.

например, если выход был запрограммирован в методе onCreate() в родительском классе, Android не удалось правильно получить вывод переопределенных методов из дочерних классов за первый ребенок. Честно говоря, я не понимаю весь порядок вызова метода.

Для решения проблемы я просто запрограммировал вывод в onResume(), и теперь он работает нормально.

Смежные вопросы