2010-01-28 20 views
5

Sono nuovo di Java e ho letto alcuni tutorial sui metodi di sovrascrittura, ma un esempio che sto guardando non funziona come mi aspetto. Ad esempio, ho il codice:Sovrascrittura di un metodo 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"); 
    } 
} 

Quando ho istanzia e si chiamo B.run(), mi sarei aspettato di vedere "B" in uscita. Tuttavia, vedo invece "A". Che cosa sto facendo di sbagliato?

Modifica: Sì, le classi si trovano in due file separati. Sono mostrati insieme per brevità.

Modifica: non sono sicuro di come viene istanziata B, poiché viene eseguita da un programma di terze parti che utilizza un classloader.

Modifica: Ulteriori informazioni sul programma di terze parti. Inizia chiamando A.main(), che inizialmente non ho mostrato (mi dispiace). Suppongo di dover creare "nuovo A(). Run();" più generico per usare il nome della classe corrente. È possibile?

+5

Come stai istanziando e chiamando questo? –

+1

@Prasoon Non è stato menzionato il file, solo le classi. Non è stato possibile dedurre i file effettivi in ​​cui si trovavano. – KLE

risposta

6

Questo codice sarà in uscita B se:

(new B()).run(); 

Qualunque sia il problema è, non è nel codice che hai citato.

Aggiornato (dopo la modifica)

Se il programma di terze parti sta chiamando A.main(), non c'è niente (ragionevole) si può fare in B che si inietterà in A. Finché A.main sta facendo new A().run(), avrà un'istanza di A, non un'istanza di B. Non esiste un "nome di classe corrente" da utilizzare, o se c'è (dipende dal tuo punto di vista), è A, non B.

Dovrete ottenere il programma di terze parti per chiamare B in qualche modo, piuttosto che A, o semplicemente modificare A direttamente (ad esempio, per liberarsi di B del tutto). Si non si desidera modificare A per utilizzarlo B; che lo lega strettamente a un discendente e rende la separazione tra di loro largamente inutile.

Spero che questo aiuti.

+0

È un peccato che Java non esponga la classe corrente in cui risiede il codice. Sono più familiare con Python, dove sarei in grado di eseguire type (self) o definire esplicitamente main() come un metodo di classe. Comunque, alla fine ho semplicemente dato a B il suo main() che istanzia direttamente B, e questo risolve il problema. – Cerin

+0

@Chris: il problema non è che Java non lo esponga (lo fa; all'interno di un metodo di istanza, 'this.getClass()' fornisce l'istanza 'Class' che ti dice tutto ciò che devi sapere sulla classe ; se sei in un metodo di classe (statico), sai già in quale classe ti trovi e puoi usare il nome - ad esempio, 'A' - direttamente per ottenere l'istanza' Class'). Questo non è il problema che stai avendo. Il problema che stai avendo è che 'B' non è coinvolto in alcun modo forma o forma quando viene chiamato' A.main'. 'B' potrebbe anche non essere lì. Non è un linguaggio, è una cosa che stai provando a fare. :-) –

+0

@ T.J. Crowder: Corretto, ma solo perché in Java non ho altra scelta che l'hardcode "nuovo A()". In Python, main() potrebbe essere un metodo di classe, il cui primo argomento sarebbe automaticamente "cls", quindi potrei istanziare la classe semplicemente facendo "cls()". Questo sarebbe ereditabile, quindi non dovrei scrivere un main separato() per B. – Cerin

3

Ho provato, mettendo le due classi in due file, e ha funzionato bene, emettendo "B". Ho chiamato:

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

AGGIORNAMENTO: funziona anche come (perché è la stessa istanza runtime):

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

'A a = new B()' dovrebbe funzionare bene (a meno che i metodi non siano statici). – Nate

+0

@Bedwyr L'output è lo stesso! :-) – KLE

1

Dipende dall'istanza. Prova questo:

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 = nuovo A(); non si compilerà, è impossibile! – KLE

+0

Ciò comporterà un errore di compilazione sulla riga 3. A non è di tipo B. –

+0

Sì, lo so, ma questo risultato è un'esperienza utile. – demas

2

Lavori per me.

Ecco il mio codice per A e 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"); 
    } 
} 

Ecco il mio punto di ingresso:

package so; 

public class EntryPoint { 

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

esso stampa 'B'.

1

Ho provato il tuo esempio e il mio risultato è stato B.

Come stai creando un'istanza? Ecco il codice esatto che ho eseguito.

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

Se il programma esterno un'istanza di A, si avrà una, non B.

Ma si può provare qualcosa di simile, con qualche riflessione, e passare "com.mypackage.A" o "com .mypackage.B "come argomenti per il tuo programma.

Con questo codice (mancata cattura di eccezioni), sarà possibile stampare "A" o "B" in base al parametro di stringa che si passa.

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

} 
Problemi correlati