2010-01-28 22 views
5

Soy nuevo en Java, y he leído algunos tutoriales sobre cómo reemplazar los métodos, pero un ejemplo que estoy viendo no funciona de la manera que esperaba. Por ejemplo, tengo el código:Anulando un Método Java

public class A{ 
    public void show(){ 
     System.out.println("A"); 
    } 
    public void run(){ 
     show(); 
    } 
    public static void main(String[] arg) { 
     new A().run(); 
    } 
} 
public class B extends A{ 
    @Override 
    public void show(){ 
     System.out.println("B"); 
    } 
} 

Cuando instanciar y llamar B.run(), yo esperaría ver "B" salen. Sin embargo, veo "A" en su lugar. ¿Qué estoy haciendo mal?

Editar: Sí, las clases están en dos archivos separados. Se muestran juntos por brevedad.

Editar: No estoy seguro de cómo se está instanciando B, ya que está siendo realizado por un programa de terceros que utiliza un cargador de clases.

Editar: Más información sobre el programa de terceros. Comienza llamando a A.main(), que inicialmente no se mostró (lo siento). Asumo que necesito hacer "nuevo A(). Run();" más genérico para usar el nombre de la clase actual. ¿Es eso posible?

+5

¿Cómo está instanciando y llamando a esto? –

+1

@Prasoon No se mencionó el archivo, solo las clases. No pudimos inferir los archivos reales en los que estaban. – KLE

Respuesta

6

Ese código es la salida B si:

(new B()).run(); 

Cualquiera que sea el problema es decir, no está en el código que has citado.

Actualizado (después de su edición)

Si el programa de terceros está llamando A.main(), no hay nada (razonable) que puede hacer en B que inyectará sí mismo en A. Mientras A.main esté haciendo new A().run(), tendrá una instancia de A, no una instancia de B. No hay un "nombre de clase actual" para usar, o si existe (depende de su punto de vista), es A, no B.

Vas a tener que conseguir el programa de terceros para llamar B de alguna manera, en lugar de A, o simplemente modificar A directamente (por ejemplo, deshacerse de B por completo). Lo hace no desea modificar A para hacer que use B; eso lo ata firmemente a un descendiente y hace la separación entre ellos en gran parte inútil.

Espero que ayude.

+0

Es una pena que Java no exponga la clase actual en la que reside el código. Estoy más familiarizado con Python, donde podría hacer type (self) o definir explícitamente main() como classmethod. De todos modos, terminé simplemente dando a B su propio main() que instancia B directamente, y eso soluciona el problema. – Cerin

+0

@Chris: El problema no es que Java no lo exponga (lo hace, dentro de un método de instancia, 'this.getClass()' le da la instancia 'Class' que le dice todo lo que necesita saber sobre la clase ; si está en un método de clase (estático), ya sabe en qué clase se encuentra y puede usar el nombre, por ejemplo, 'A' - directamente para obtener la instancia' Class'). Ese no es el problema que estás teniendo. El problema que tienes es que 'B' simplemente no está involucrado de ninguna forma o forma cuando se llama a' A.main'. 'B 'bien podría no estar allí. No es algo del lenguaje, es algo de lo que estás tratando de hacer. :-) –

+0

@ T.J. Crowder: Correcto, pero solo porque en Java no tengo más remedio que codificar "nuevo A()". En Python, main() podría ser un classmethod, cuyo primer argumento sería automáticamente "cls", por lo que podría instanciar la clase simplemente haciendo "cls()". Esto sería heredable, por lo que no tendría que escribir un main() separado para B. – Cerin

3

Lo intenté, poniendo sus dos clases en dos archivos, y funcionó muy bien, sacando "B". Llamé:

B b = new B(); 
b.run(); 

ACTUALIZACIÓN: También funciona como (porque es la misma instancia de tiempo de ejecución):

A a = new B(); 
a.run(); 
+1

'A a = new B()' debería funcionar bien también (a menos que los métodos sean estáticos). – Nate

+0

@Bedwyr ¡El resultado es el mismo! :-) – KLE

1

Depende de crear instancias. Pruebe esto:

A v1 = new A(); 
A v2 = new B(); 
B v3 = new A(); 
B v4 = new B(); 

v1.run() 
v2.run() 
v3.run() 
v4.run() 
+3

B v3 = nuevo A(); no compilará, ¡es imposible! – KLE

+0

Esto dará como resultado un error de compilación en la línea 3. A no es del tipo B. –

+0

Sí, lo sé, pero este resultado es una experiencia útil. – demas

2

Funciona para mí.

Aquí está mi código para A y B:

package so; 

public class A{ 
    public void show(){ 
     System.out.println("A"); 
    } 
    public void run(){ 
     show(); 
    } 
} 

class B extends A{ 
    @Override 
    public void show(){ 
     System.out.println("B"); 
    } 
} 

Aquí está mi punto de entrada:

package so; 

public class EntryPoint { 

    public static void main(String[] args) { 
     B b = new B(); 
     b.run(); 
    } 
} 

Se imprime 'B'.

1

He probado su ejemplo y mi salida fue B.

¿Cómo está creando instancias? Aquí está el código exacto que ejecuté.

public class Test { 
    public static class A { 
     public void show() { 
      System.out.println("A"); 
     } 

     public void run() { 
      show(); 
     } 
    } 

    public static class B extends A { 
     @Override 
     public void show() { 
      System.out.println("B"); 
     } 
    } 

    public static void main(String args[]) { 
     A a = new B(); 

     a.run(); 
    } 
} 
1

Si su programa externo instancia A, que tendrá A, no B.

Pero se puede intentar algo como esto, usando una reflexión, y pasar "com.mypackage.A" o "com .mypackage.B "como argumentos para su programa.

Con este código (falta la excepción), podrá imprimir "A" o "B" dependiendo del parámetro de cadena que pase.

public static void main(String[] arg) { 
    String className = arg[0]; 
    Class myClass = Class.forName(className); 
    Constructor cons = myClass.getConstructor(new Class[0]); 
    A myObject = (A) cons.newInstance(new Object[0]); 
    myObject.show(); 

} 
Cuestiones relacionadas