Kann jemand ein einfaches Beispiel liefern, das den Unterschied zwischen dynamischem und statischem Polymorphismus in Java erklärt?
java
oop
polymorphism
overloading
overriding
Prabhakar Manthena
quelle
quelle
Antworten:
Polymorphismus
1. Statische Bindung / Compile-Time-Bindung / Early Binding / Methodenüberladung (in derselben Klasse)
2. Dynamische Bindung / Laufzeitbindung / Späte Bindung / Überschreiben von Methoden (in verschiedenen Klassen)
Überladungsbeispiel:
übergeordnetes Beispiel:
quelle
Animal reference but Dog object
, warum können wir nicht verwendenDog reference and dog object
?Methodenüberladung wäre ein Beispiel für statischen Polymorphismus
Das Überschreiben wäre ein Beispiel für dynamischen Polymorphismus.
Denn im Falle einer Überladung weiß der Compiler zur Kompilierungszeit, welche Methode mit dem Aufruf verknüpft werden muss. Es wird jedoch zur Laufzeit für den dynamischen Polymorphismus bestimmt
quelle
Dynamischer (Laufzeit-) Polymorphismus ist der zur Laufzeit vorhandene Polymorphismus. Hier versteht der Java-Compiler nicht, welche Methode zur Kompilierungszeit aufgerufen wird. Nur JVM entscheidet, welche Methode zur Laufzeit aufgerufen wird. Das Überladen von Methoden und das Überschreiben von Methoden mithilfe von Instanzmethoden sind Beispiele für dynamischen Polymorphismus.
Beispielsweise,
Stellen Sie sich eine Anwendung vor, die verschiedene Dokumenttypen serialisiert und de-serialisiert.
Wir können 'Dokument' als Basisklasse und verschiedene daraus abgeleitete Dokumenttypklassen haben. ZB XMLDocument, WordDocument usw.
Die Dokumentklasse definiert die Methoden 'Serialize ()' und 'De-serialize ()' als virtuell, und jede abgeleitete Klasse implementiert diese Methoden auf ihre eigene Weise basierend auf dem tatsächlichen Inhalt der Dokumente.
Wenn verschiedene Dokumenttypen serialisiert / de-serialisiert werden müssen, werden die Dokumentobjekte durch die Klassenreferenz (oder den Zeiger) 'Document' referenziert, und wenn die Methode 'Serialize ()' oder 'De-serialize ()' aufgerufen wird Darauf werden entsprechende Versionen der virtuellen Methoden aufgerufen.
Statischer Polymorphismus (Kompilierungszeit) ist der Polymorphismus, der zur Kompilierungszeit gezeigt wird. Hier weiß der Java-Compiler, welche Methode aufgerufen wird. Methodenüberladung und Methodenüberschreibung mit statischen Methoden; Methodenüberschreibungen mit privaten oder endgültigen Methoden sind Beispiele für statischen Polymorphismus
Beispielsweise,
Ein Mitarbeiterobjekt kann zwei print () -Methoden haben, eine ohne Argumente und eine mit einer Präfixzeichenfolge, die zusammen mit den Mitarbeiterdaten angezeigt wird.
Wenn angesichts dieser Schnittstellen die print () -Methode ohne Argumente aufgerufen wird, weiß der Compiler anhand der Funktionsargumente, welche Funktion aufgerufen werden soll, und generiert den Objektcode entsprechend.
Weitere Informationen finden Sie unter "Was ist Polymorphismus" (Google it).
quelle
Dieses Bild zeigt deutlich, was bindend ist.
In diesem Bild ist der Aufruf von "a1.methodOne ()" an die entsprechende Definition von methodOne () und der Aufruf von "a1.methodTwo ()" an die entsprechende Definition von methodTwo () gebunden.
Für jeden Methodenaufruf sollte eine korrekte Methodendefinition vorhanden sein. Dies ist eine Regel in Java. Wenn der Compiler nicht für jeden Methodenaufruf die richtige Methodendefinition sieht, wird ein Fehler ausgegeben.
Kommen Sie nun zu statischer Bindung und dynamischer Bindung in Java.
Statische Bindung in Java:
.
Die statische Bindung kann wie im folgenden Bild gezeigt werden.
In diesem Bild ist 'a1' eine Referenzvariable vom Typ Klasse A, die auf ein Objekt der Klasse A zeigt. 'A2' ist ebenfalls eine Referenzvariable vom Typ Klasse A, zeigt jedoch auf ein Objekt der Klasse B.
Während der Kompilierung überprüft der Compiler während der Bindung nicht den Objekttyp, auf den eine bestimmte Referenzvariable zeigt. Es wird lediglich der Typ der Referenzvariablen überprüft, über die eine Methode aufgerufen wird, und es wird geprüft, ob in diesem Typ eine Methodendefinition dafür vorhanden ist.
Beispielsweise prüft der Compiler für den Methodenaufruf "a1.method ()" im obigen Bild, ob eine Methodendefinition für method () in Klasse A vorhanden ist. Da 'a1' vom Typ Klasse A ist. In ähnlicher Weise wird beim Methodenaufruf "a2.method ()" geprüft, ob in Klasse A eine Methodendefinition für method () vorhanden ist. Da 'a2' auch vom Typ Klasse A ist. Es wird nicht überprüft, auf welches Objekt 'a1' und 'a2' zeigen. Diese Art der Bindung wird als statische Bindung bezeichnet.
Dynamische Bindung in Java:
Zur Laufzeit werden tatsächliche Objekte zum Binden verwendet. Zum Beispiel wird für den Aufruf von "a1.method ()" im obigen Bild die Methode () des tatsächlichen Objekts aufgerufen, auf das 'a1' zeigt. Beim Aufruf von "a2.method ()" wird method () des tatsächlichen Objekts aufgerufen, auf das 'a2' zeigt. Diese Art der Bindung wird als dynamische Bindung bezeichnet.
Die dynamische Bindung des obigen Beispiels kann wie unten gezeigt werden.
Referenz statische Bindung und dynamische Bindung in Java
quelle
Polymorphismus: Polymorphismus ist die Fähigkeit eines Objekts, viele Formen anzunehmen. Die häufigste Verwendung von Polymorphismus in OOP tritt auf, wenn eine übergeordnete Klassenreferenz verwendet wird, um auf ein untergeordnetes Klassenobjekt zu verweisen.
Dynamische Bindung / Laufzeitpolymorphismus:
Laufzeit-Polymorphismus, auch als Methodenüberschreibung bezeichnet. In diesem Mechanismus wird ein Aufruf einer überschriebenen Funktion zur Laufzeit aufgelöst.
Ausgabe:
Innenstartmethode des Autos
Statischer Bindungs- / Kompilierungszeitpolymorphismus:
Welche Methode aufgerufen werden soll, wird nur zur Kompilierungszeit entschieden.
Ausgabe: Innerhalb der Sammlung sortieren Metho
quelle
Das Überladen von Methoden ist ein Beispiel für Kompilierungszeit / statischen Polymorphismus, da die Methodenbindung zwischen Methodenaufruf und Methodendefinition zur Kompilierungszeit erfolgt und von der Referenz der Klasse abhängt (Referenz wird zur Kompilierungszeit erstellt und geht zum Stapel).
Das Überschreiben von Methoden ist ein Beispiel für Laufzeit / dynamischen Polymorphismus, da die Methodenbindung zwischen Methodenaufruf und Methodendefinition zur Laufzeit erfolgt und vom Objekt der Klasse abhängt (Objekt, das zur Laufzeit erstellt wird und zum Heap wechselt).
quelle
In einfachen Worten :
Statischer Polymorphismus : Der gleiche Methodenname wirdmit unterschiedlichen Typen oder Anzahlen von Parametern in derselben Klasse (unterschiedliche Signatur) überladen . Der gezielte Methodenaufruf wird zur Kompilierungszeit aufgelöst.
Dynamischer Polymorphismus : Dieselbe Methode wirdin verschiedenen Klassen mit derselben Signatur überschrieben . Der Objekttyp, für den die Methode aufgerufen wird, ist zur Kompilierungszeit nicht bekannt, wird jedoch zur Laufzeit festgelegt.
Im Allgemeinen wird Überladung nicht als Polymorphismus betrachtet.
Von der Java-Tutorial- Seite :
quelle
Generally overloading won't be considered as polymorphism.
Können Sie bitte auf diesen Punkt näher eingehen?Das Überladen von Methoden wird als statischer Polymorphismus bezeichnet und auch als Polymorphismus der Kompilierungszeit oder statische Bindung bezeichnet, da überladene Methodenaufrufe zur Kompilierungszeit vom Compiler auf der Grundlage der Argumentliste und der Referenz, für die wir die Methode aufrufen, aufgelöst werden.
Das Überschreiben von Methoden wird als dynamischer Polymorphismus oder einfacher Polymorphismus oder Laufzeit-Methodenversand oder dynamische Bindung bezeichnet, da überschriebene Methodenaufrufe zur Laufzeit aufgelöst werden.
Um zu verstehen, warum dies so ist, nehmen wir ein Beispiel
Mammal
und eineHuman
KlasseIch habe die Ausgabe sowie den Bytecode der folgenden Codezeilen eingefügt
Wenn wir uns den obigen Code ansehen, können wir sehen, dass die Bytecodes von humanMammal.speak (), human.speak () und human.speak ("Hindi") völlig unterschiedlich sind, da der Compiler anhand der Argumentliste zwischen ihnen unterscheiden kann und Klassenreferenz. Aus diesem Grund wird Method Overloading als statischer Polymorphismus bezeichnet .
Der Bytecode für anyMammal.speak () und humanMammal.speak () ist jedoch identisch, da laut Compiler beide Methoden für die Mammal-Referenz aufgerufen werden. Die Ausgabe für beide Methodenaufrufe ist jedoch unterschiedlich, da JVM zur Laufzeit weiß, welches Objekt eine Referenz enthält, und JVM aufruft Die Methode für das Objekt und aus diesem Grund wird das Überschreiben von Methoden als dynamischer Polymorphismus bezeichnet.
Aus dem obigen Code und Bytecode geht hervor, dass während der Kompilierungsphase die Aufrufmethode vom Referenztyp berücksichtigt wird. Zur Ausführungszeit wird die Methode jedoch von dem Objekt aufgerufen, das die Referenz enthält.
Wenn Sie mehr darüber erfahren möchten, lesen Sie mehr darüber, wie JVM das Überladen und Überschreiben von Methoden intern handhabt .
quelle
Statischer Polymorphismus: Hier wird die Entscheidung, welche Methode ausgeführt werden soll, während der Kompilierungszeit festgelegt. Ein Beispiel hierfür könnte das Überladen von Methoden sein.
Dynamischer Polymorphismus: Hier wird die Entscheidung zur Auswahl der auszuführenden Methode zur Laufzeit festgelegt. Das Überschreiben von Methoden könnte ein Beispiel dafür sein.
quelle
Polymorphismus bezieht sich auf die Fähigkeit eines Objekts, sich für denselben Auslöser unterschiedlich zu verhalten.
Statischer Polymorphismus (Polymorphismus zur Kompilierungszeit)
Dynamischer Polymorphismus (Laufzeitpolymorphismus)
quelle
Kompilierungszeitpolymorphismus (statische Bindung / frühe Bindung): Wenn wir im statischen Polymorphismus eine Methode in unserem Code aufrufen, wird die Definition dieser Methode tatsächlich nur zur Kompilierungszeit aufgelöst.
(oder)
Zur Kompilierungszeit weiß Java, welche Methode durch Überprüfen der Methodensignaturen aufgerufen werden muss. Dies wird als Polymorphismus zur Kompilierungszeit oder statische Bindung bezeichnet.
Dynamischer Polymorphismus (Late Binding / Runtime Polymorphism): Zur Laufzeit wartet Java bis zur Laufzeit, um festzustellen, auf welches Objekt in der Referenz tatsächlich verwiesen wird. Die Methodenauflösung wurde zur Laufzeit durchgeführt, was wir als Laufzeitpolymorphismus bezeichnen.
quelle
Betrachten Sie den folgenden Code:
Wenn Sie sich nun den Code ansehen, können Sie nie sagen, welche Implementierung von methodA () ausgeführt wird, da dies davon abhängt, welchen Wert der Benutzer zur Laufzeit gibt. Es wird also nur zur Laufzeit entschieden, welche Methode aufgerufen wird. Daher Laufzeitpolymorphismus.
quelle
Das Überladen von Methoden ist ein Polymorphismus zur Kompilierungszeit. Nehmen wir ein Beispiel, um das Konzept zu verstehen.
In diesem Beispiel hat Person eine Essmethode, die angibt, dass sie entweder Pizza oder Nudeln essen kann. Daß die Methode eat beim Kompilieren dieser Person.java überladen ist, löst der Compiler den Methodenaufruf "e.eat (Nudeln) [in Zeile 6] mit der in Zeile 8 angegebenen Methodendefinition auf. Dies ist die Methode, die Nudeln als Parameter verwendet und der gesamte Prozess wird vom Compiler ausgeführt, so dass es sich um Polymorphismus zur Kompilierungszeit handelt. Der Prozess des Ersetzens des Methodenaufrufs durch die Methodendefinition wird als Bindung bezeichnet. In diesem Fall wird er vom Compiler ausgeführt, sodass er als frühe Bindung bezeichnet wird.
quelle
Nach Nareshs Antwort ist dynamischer Polymorphismus in Java nur "dynamisch", da die virtuelle Maschine vorhanden ist und der Code zur Laufzeit interpretiert werden kann und nicht der Code, der nativ ausgeführt wird.
In C ++ muss es zur Kompilierungszeit aufgelöst werden, wenn es offensichtlich mit gcc zu einer nativen Binärdatei kompiliert wird. Der Laufzeitsprung und Thunk in der virtuellen Tabelle wird jedoch weiterhin als "Lookup" oder "Dynamic" bezeichnet. Wenn C B erbt und Sie deklarieren , zeigt c bereits auf das äußere C-Objekt und der Zeiger wird an C :: method1 () im Textsegment übergeben. Siehe: http://www.programmersought.com/article/2572545946/
B* b = new C(); b->method1();
, wird b vom Compiler aufgelöst, um auf ein B-Objekt in C zu verweisen (für eine einfache Klasse erbt eine Klassensituation, das B-Objekt in C und C beginnt an derselben Speicheradresse, also nichts muss durchgeführt werden, es wird auf das vptr zeigen, das beide verwenden). Wenn C B und A erbt, hat die virtuelle Funktionstabelle des A-Objekts im C-Eintrag für Methode1 einen Thunk, der den Zeiger auf den Anfang des einkapselnden C-Objekts versetzt und ihn dann an die reale A :: -Methode1 () übergibt. in dem Textsegment, das C überschrieben hat. ZumC* c = new C(); c->method1()
In Java kann
B b = new C(); b.method1();
die virtuelle Maschine den Typ des mit b gepaarten Objekts dynamisch überprüfen, den richtigen Zeiger übergeben und die richtige Methode aufrufen. Der zusätzliche Schritt der virtuellen Maschine macht virtuelle Funktionstabellen oder den Typ, der zur Kompilierungszeit aufgelöst wird, überflüssig, selbst wenn er zur Kompilierungszeit bekannt sein könnte. Es ist nur eine andere Methode, die sinnvoll ist, wenn eine virtuelle Maschine beteiligt ist und Code nur zu Bytecode kompiliert wird.quelle