2010-01-28 8 views
5

Ich bin neu in Java und habe einige Tutorials zum Überschreiben von Methoden gelesen, aber ein Beispiel, das ich mir anschaut, funktioniert nicht so, wie ich es erwarte. Zum Beispiel habe ich den Code:Eine Java-Methode überschreiben

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

Als ich instanziiert und rufen B.run(), würde ich erwarten, "B" ausgegeben zu sehen. Allerdings sehe ich stattdessen "A". Was mache ich falsch?

Edit: Ja, die Klassen sind in zwei separaten Dateien. Sie werden zusammen der Kürze halber gezeigt.

Bearbeiten: Ich bin mir nicht sicher, wie B instanziiert wird, da es von einem Drittanbieter-Programm mit einem Classloader durchgeführt wird.

Bearbeiten: Weitere Informationen zum Drittanbieter-Programm. Es beginnt mit dem Aufruf von A.main(), was ich anfangs nicht gezeigt habe (Entschuldigung). Ich nehme an, ich muss "new A(). Run();" generischer, um den Namen der aktuellen Klasse zu verwenden. Ist das möglich?

+5

Wie werden Sie dies instanziieren und aufrufen? –

+1

@Prasoon Es gab keine Erwähnung von Datei, nur Klassen. Wir konnten nicht auf die tatsächlichen Dateien schließen, in denen sie sich befanden. – KLE

Antwort

6

Dieser Code wird ausgegeben B, wenn Sie:

(new B()).run(); 

Was auch immer das Problem ist, ist es nicht in dem Code, den Sie zitiert haben.

Aktualisiert (nach dem edit)

Wenn der Fremdanbieter-Programm ist A.main() Aufruf, gibt es nichts (vernünftig) Sie in B tun können, die sich in A injizieren. Solange A.mainnew A().run() tut, wird es eine Instanz von A haben, keine Instanz von B. Es gibt keinen "aktuellen Klassennamen" zu verwenden, oder wenn es (abhängig von Ihrer Sicht) ist, ist es A, nicht B.

Sie werden die Fremdanbieter-Programm erhalten müssen B in irgendeiner Weise zu nennen, anstatt A, oder einfach nur A direkt ändern (zum Beispiel von B ganz loszuwerden). Sie tun nicht möchten A ändern, damit es B verwenden; das bindet es eng an einen Nachkomme und macht die Trennung zwischen ihnen weitgehend sinnlos.

Hoffe, dass hilft.

+0

Es ist schade, Java nicht die aktuelle Klasse aussetzen des Code befindet. Ich bin mehr vertraut mit Python, wo ich in der Lage sein würde Art (Selbst-) oder explizit zu tun definiert main() als Class. Wie auch immer, am Ende habe ich B einfach sein eigenes main() gegeben, das B direkt instanziiert, und das behebt das Problem. – Cerin

+0

@ Chris: Das Problem ist nicht, dass Java verfügbar macht es nicht (es tut, innerhalb einer Instanz Methode 'this.getClass()' gibt Ihnen die 'CLASS' Instanz, die Sie alles, was Sie über die Klasse wissen müssen, sagt Wenn Sie sich in einer (statischen) Klassenmethode befinden, wissen Sie bereits, in welcher Klasse Sie sich befinden und können den Namen verwenden - zB "A" - direkt, um die "Klassen" -Instanz zu erhalten. Das ist nicht das Problem, das du hast. Das Problem, das Sie haben, ist, dass "B" einfach nicht in irgendeiner Form oder Form beteiligt ist, wenn "A.main" aufgerufen wird. 'B' kann genauso gut nicht da sein. Es ist keine Sprachsache, es ist eine Was-Du-versuchen-zu-tun-Sache. :-) –

+0

@ T.J. Crowder: Korrekt, aber nur weil ich in Java keine andere Wahl habe als "new A()" zu schreiben. In Python könnte main() eine Klassenmethode sein, deren erstes Argument automatisch "cls" wäre, also könnte ich die Klasse instanziieren, indem ich einfach "cls()" mache. Dies wäre vererbbar, so dass ich für mE keine separate main() schreiben müsste. – Cerin

3

Ich habe versucht, Ihre zwei Klassen in zwei Dateien, und es funktionierte gut, Ausgabe "B". Ich rief:

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

AKTUALISIERT: Funktioniert auch als (weil es die gleiche Laufzeitinstanz):

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

'A a = new B()' sollte auch funktionieren (außer die Methoden sind statisch). – Nate

+0

@Bedwyr Die Ausgabe ist gleich! :-) – KLE

1

Es hängt von der Instanziierung ab. Versuchen Sie dies:

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 = neu A(); wird nicht kompilieren, es ist unmöglich! – KLE

+0

Dies führt zu einem Kompilierungsfehler in Zeile 3. A ist nicht vom Typ B. –

+0

Ja, ich weiß es, aber dieses Ergebnis ist eine nützliche Erfahrung. – demas

2

Funktioniert für mich.

Hier ist mein Code für A und 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"); 
    } 
} 

Hier ist mein Einstiegspunkt:

package so; 

public class EntryPoint { 

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

Es druckt 'B'.

1

habe ich versucht, Ihr Beispiel und meine Ausgabe war B.

Wie instanziieren Sie? Hier ist der genaue Code, den ich ausgeführt habe.

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

Wenn Ihr externes Programm A instanziiert, werden Sie A, nicht B.

Aber man kann so etwas wie dies versuchen, einige Überlegungen mit, und übergeben „com.mypackage.A“ oder „com .mypackage.B "als Argumente für Ihr Programm.

Mit diesem Code (Ausnahme Fang fehlt), können Sie „A“ oder „B“ in Abhängigkeit von den String-Parametern drucken, die Sie weitergeben.

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

}