2012-03-28 20 views
5

Vererbung und Polymorphie bilden eine IS-A-Beziehung? Und ist es wahr, dass Vererbung und "overriding" Polymorphismus in der Laufzeit passieren, während "Überladen" Polymorphismus in der Kompilierzeit auftritt? Der Grund, warum ich das frage, ist, dass viele Foren widersprüchliche und oft verwirrende Antworten geben.Java Vererbung vs Polymorphismus

Danke!

+3

Ich denke, Überladung hat nichts mit Polymorphie zu tun. – ka3ak

+0

Eigentlich ist dies eine Form des Pollymorphismus: Aus Wikipedia: Der Begriff Ad-hoc-Polymorphismus bezieht sich auf polymorphe Funktionen, die auf Argumente unterschiedlicher Typen angewendet werden können, sich aber je nach Art des Arguments unterschiedlich verhalten (auch bekannt als Überlastung der Funktion oder Überlastung des Operators). –

+0

@edalorzo: faktische Genauigkeit von http://en.wikipedia.org/wiki/Ad-hoc_polymorphism ist umstritten. – Jayan

Antwort

8

Für Ihren ersten Teil der Frage, die ich denke, Wikipedia bietet eine gute Definition:

In der objektorientierten Programmierung, Subtyp Polymorphismus oder Inklusion Polymorphismus ist ein Konzept in der Typentheorie, wobei ein Name Instanzen von vielen verschiedenen Klassen bezeichnen kann, solange sie durch einige gemeinsame Superklasse verwandt sind. Einschlusspolymorphismus wird im Allgemeinen durch Subtyping unterstützt, d. H. Objekte unterschiedlicher Typen sind für Objekte eines anderen Typs (ihre Basis (n)) vollständig substituierbar und können daher über eine gemeinsame Schnittstelle gehandhabt werden. Alternativ kann Einschlusspolymorphismus durch Typ Zwang, auch bekannt als Typ Casting erreicht werden.

Ein anderer Wikipedia-Artikel namens Polymorphism in object-oriented programming scheint Ihre Fragen sehr gut zu beantworten. Die zweite Referenz in diesem Artikel mit der Bezeichnung On Understanding Types, Data Abstraction, and Polymorphism deckt dieses Thema ebenfalls sehr detailliert ab.

Diese Untertypisierung in Java wird unter anderem durch Vererbung von Klassen und Schnittstellen erreicht. Obwohl die Subtyping-Features von Java möglicherweise nicht immer in Bezug auf die Vererbung erkennbar sind. Nehmen wir zum Beispiel die Fälle von Kovarianz und Kontravarianz mit Generika. Arrays sind auch serialisierbar und kopierbar, obwohl dies nirgendwo in der Typhierarchie offensichtlich ist. Es kann auch gesagt werden, dass durch die primitive Verbreiterungskonvertierung auch numerische Typen in Java polymorph sind. Und der Operator verhält sich abhängig von seinen Operanden polymorph.

In jedem Fall spielt die Vererbung eine wichtige Rolle bei der Umsetzung einiger dieser Polymorphismen.

Überlastung vs Zwingende

Ihre zweite Teil der Frage scheint über die Wahl der Implementierung einer bestimmten Methode. Wenn eine Klasse eine Methode überschreibt und Sie eine Instanz dieser Klasse erstellen, möchten Sie offensichtlich, dass die überschriebene Version der Methode aufgerufen wird, selbst wenn Sie über eine Referenz der übergeordneten Klasse auf das Objekt zugreifen.

Die Auswahl der richtigen Implementierung der Methode erfolgt zur Laufzeit, wie Sie genau hinwiesen, jetzt wird die Signatur der Methode, die aufgerufen werden soll, zur Kompilierzeit entschieden. Da es beim Überladen um verschiedene Methoden mit dem gleichen Namen und unterschiedlicher Signatur geht, wird gesagt, dass die Überschreibung der Methoden zur Kompilierungszeit erfolgt.

Aufschalten Methodenauswahl zur Kompilierzeit

Die Java Language Specification (JLS) in Abschnitt 15.12 Method Invocation Expressions im Detail erläutert den Prozess, der der Compiler die richtige Methode zur Auswahl folgt aufzurufen.

Dort werden Sie feststellen, dass dies eine Kompilierzeit Aufgabe ist. Die JLS sagt in Abschnitt 15.12.2:

Dieser Schritt verwendet die Namen der Methode und die Typen des Arguments Ausdrücke Methoden zu finden, die sowohl zugänglich und anwendbar sind Es kann mehr als eine solche Methode, in diesem Fall wird die spezifischste gewählt.

Um die Kompilierzeit zu überprüfen, können Sie den folgenden Test durchführen.

Deklarieren Sie eine Klasse wie diese und kompilieren Sie sie.

public class ChooseMethod { 
    public void doSomething(Number n){ 
    System.out.println("Number"); 
    } 
} 

Deklarieren Sie eine zweite Klasse, die eine Methode der ersten aufruft und kompilieren Sie sie.

public class MethodChooser { 
    public static void main(String[] args) { 
    ChooseMethod m = new ChooseMethod(); 
    m.doSomething(10); 
    } 
} 

Wenn Sie die Haupt aufrufen, sagt der Ausgang Number. Jetzt

, fügen Sie eine zweite speziellere überlastet Methode zum ChooseMethod Klasse und neu kompilieren (aber nicht die andere Klasse neu kompilieren).

public void doSomething(Integer i) { 
System.out.println("Integer"); 
} 

Wenn Sie die Haupt erneut ausführen, ist der Ausgang noch Number.

Grundsätzlich, weil es zur Kompilierzeit entschieden wurde. Wenn Sie die Klasse MethodChooser (die mit der Hauptkomponente) neu kompilieren und das Programm erneut ausführen, lautet die Ausgabe Integer.

Wenn Sie also die Auswahl einer der überladenen Methoden erzwingen möchten, muss der Typ der Argumente zum Zeitpunkt der Kompilierung und nicht nur zur Laufzeit dem Typ der Parameter entsprechen.

zur Laufzeit Methodenauswahl Aufschalten

Auch hier wird die Signatur der Methode bei der Kompilierung entschieden, aber die tatsächliche Umsetzung wird zur Laufzeit entschieden.

Deklarieren Sie eine Klasse wie diese und kompilieren Sie sie.

public class ChooseMethodA { 
    public void doSomething(Number n){ 
    System.out.println("Number A"); 
    } 
} 

Dann eine zweite Verlängerung Klasse deklarieren und kompilieren:

public class ChooseMethodB extends ChooseMethodA { } 

Und in der MethodChooser Klasse, die Sie tun:

public class MethodChooser { 
    public static void main(String[] args) { 
     ChooseMethodA m = new ChooseMethodB(); 
     m.doSomething(10); 
    } 
} 

Und wenn Sie es ausführen erhalten Sie die Ausgabe Number A und Dies ist in Ordnung, da das Verfahren wird in ChooseMethodB und daher wird die Implementierung ist, dass die ChooseMethodA aufgerufen nicht außer Kraft gesetzt worden ist.

public void doSomething(Number n){ 
    System.out.println("Number B"); 
} 

und neu kompilieren gerade diese, und das Hauptverfahren erneut aus:

nun eine überschriebene Methode in MethodChooserB hinzuzufügen.

Jetzt erhalten Sie die Ausgabe Number B

Als solche wurde die Implementierung zur Laufzeit gewählt, und nicht die Neuübersetzung der MethodChooser Klasse erforderlich war.

+2

Die Antwort von Jayan ist ziemlich prägnant, denke ich. – shiva

0

Polymorphie ist ein Effekt der Vererbung. Das kann nur in Klassen passieren, die sich gegenseitig ergänzen.

Polymorphismus tritt zur Laufzeit auf; Ich habe noch nie von "Überladung Polymorphismus" gehört.

Vererbung bei der Kompilierung geschieht, sobald Sie schreiben:

class A extends B 
{ 
} 
0

Nur Vererbung eine IS-A-Beziehung dar. Polymorphismus hat damit nichts zu tun.

"Überladung" ist ein Beispiel für Polymorphie. Sie können mehr über Laufzeit lernen und Compiler-Polymorphismus here

1

Ich glaube, du hast Recht.

Polymorphismus berücksichtigt den Laufzeittyp des Objekts, um zu entscheiden, welche Methode ausgeführt wird und welche Auswahl der überladenen Methode zur Laufzeit nicht dynamisch festgelegt wird. Sie hängt von den Typen der Parameter zum Zeitpunkt der Kompilierung ab.

5

Polymorphismus: Die Fähigkeit von verschiedenen Objekten gleiche Nachricht zu empfangen und reagieren unterschiedlich auf.

Vererbung eine Möglichkeit, es zu erreichen, aber nicht notwendig. Siehe Duck Typing

Überladen einer Methode ist 'Kompilierzeit Syntax Helfer' - wie jede Methode erhält eine eindeutige Signatur nach der Kompilierung. Nicht wirklich etwas mit Polymorphismus zu tun.

0

• Vererbung definiert Eltern-Kind-Beziehung zwischen zwei Klassen, Polymorphismus nutzt diese Beziehung dynamisches Verhalten in Ihrem Code hinzuzufügen.

• Vererbung fördert Wiederverwendbarkeit von Code, indem Kind Klassenverhalten von der übergeordneten Klasse erben. Auf der anderen Seite erlaubt Polymorphism dem Kind, bereits definiertes Verhalten innerhalb der Elternklasse neu zu definieren. Ohne Polymorphie ist es nicht möglich, dass ein Kind sein eigenes Verhalten ausführt, während es durch eine Eltern-Referenzvariable repräsentiert wird, aber mit Polymorphismus kann es gemacht werden.

• Java erlaubt keine mehrfache Vererbung von Klassen, erlaubt aber die mehrfache Vererbung von Interface, die zur Implementierung von Polymorphismus benötigt wird. Zum Beispiel kann eine Klasse gleichzeitig Runnable, Comparator und Serializable sein, da alle drei Schnittstellen sind. Dies führt dazu, dass sie im Code z. Sie können eine Instanz dieser Klasse an eine Methode übergeben, die Serializable akzeptiert, oder an Collections.sort(), die einen Comparator akzeptiert.

• Sowohl der Polymorphismus als auch die Vererbung ermöglichen die Entwicklung objektorientierter Programme. Wenn Sie beispielsweise Vererbung verwenden, können Sie neue Benutzertypen in einem Authentifizierungssystem definieren und mithilfe von Polymorphism den bereits geschriebenen Authentifizierungscode nutzen. Da die Vererbung das Mindestverhalten der Basisklasse garantiert, kann eine Methode, die von der Superklasse oder Superschnittstelle abhängt, ein Objekt der Basisklasse akzeptieren und es authentifizieren.