2009-04-10 22 views
5

que tienen las siguientes clases:¿La superclase no llama al método reemplazado?

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

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

Cuando ahora llamo bar.b() lo quiero para llamar al método reemplazado un() en foo. Sin embargo, imprime "a".

+3

Perdón por lo didáctico: Se llama "sobrescribir", no "sobrescribir". – erickson

+0

El código tal como lo ha escrito debe funcionar como espera: como muchas de las respuestas a continuación sugieren obtener el resultado que está obteniendo, debe estar haciendo algo más en su código que no se muestra aquí. – Eborbob

Respuesta

7

Cuando ejecuto el siguiente:

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

me sale el siguiente resultado:

overwritten a 

que es lo que esperaría a ver.

+0

Me ganaste un minuto. Obtengo el mismo resultado. – Eddie

+0

Puede ser que él le ganó en la publicación, de lo contrario, creo que obtuvimos este resultado antes de que se publique esta pregunta. –

9

Puede ser que estés tratando de usar métodos estáticos, que no funcionarán ya que no se anulan.

Una buena manera de comprobar es añadir la anotación @ Override a bar.a() y ver si el compilador le da un error que un() no es en realidad nada overidding

+2

+1 para la recomendación @Override – Rob

0

Usted puede ser confundido si vienes de C# o de algún otro idioma donde tienes que declarar explícitamente funciones virtuales y/o funciones generales.

En Java, todas las funciones de instancia son virtuales y se pueden anular, a menos que se declaren como privadas y/o finales.

No es necesario especificar la nueva anotación @Override para hacerlo, agregando que la anotación solo especifica que su intención es anular, y causará una advertencia o un error si no es una anulación. (Si accidentalmente escribió mal el nombre del método, por ejemplo).

El ejemplo de Andrew muestra cómo debería funcionar esto.

10

¿Están sus dos clases en paquetes diferentes? ¿Y sus métodos de clase Foo se declaran públicos, protegidos o privados o de paquete local? Obviamente, si son privados, esto no funcionará. Tal vez sea menos obvio, si son paquetes locales (es decir, sin alcance público/protegido/privado), entonces solo puede anularlos si está en el mismo paquete que la clase original.

Por ejemplo:

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

En este caso, seguirá recibiendo 'A'. Si declara que el método a() original en Foo es público o está protegido, obtendrá el resultado que esperaba.

+2

Este fue mi problema; cambiando el método de supertipo a protegido lo solucionó. Lo que no entiendo es por qué la etiqueta @Override en el método de subtipo no hizo que el compilador me diera un mensaje de error si no iba a funcionar. – shieldgenerator7

0

De la boca del caballo:

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

"La versión del método reemplazado que se invoca es el de la subclase La versión del método oculto que se invoca depende de si se invoca. de la superclase o la subclase ".

Entonces, si ambos son métodos estáticos e invoca el método de la superclase, se invoca el método de superclase, no el método de la subclase. Entonces, realmente, no se está imponiendo nada.

-1

Mientras estaba trabajando en un programa de Android, tuve el mismo problema en mis clases de Java. Resultó que el problema no estaba en las clases, sino en la forma en que el marco de Android procesa la salida de pantalla.

por ejemplo, si la salida se programó en el método onCreate() en la clase principal, Android no obtuvo correctamente la salida de los métodos reemplazados de las clases secundarias después del primer hijo. Honestamente, no entiendo todo el orden de llamadas de método.

Para resolver el problema, simplemente programé la salida en onResume() y ahora parece funcionar bien.

Cuestiones relacionadas