Was ist der Unterschied zwischen dynamischem und statischem Polymorphismus in Java?

117

Kann jemand ein einfaches Beispiel liefern, das den Unterschied zwischen dynamischem und statischem Polymorphismus in Java erklärt?

Prabhakar Manthena
quelle
4
Überschreibungen werden manchmal als "statischer Polymorphismus" bezeichnet. Das spannt die Dinge ein bisschen, aber genau das ist los.
Dasblinkenlight
@dasblinkenlight danke für die Info. Gibt es ein Beispiel dafür?
Prabhakar Manthena
Suchen Sie nach "Methodenüberladung" und "Methodenüberschreibung".
Dasblinkenlight
5
Ich verstehe nicht, wie Überlastung Polymorphismus ist. Polymorphismus ist ein Objektbegriff. Wir sollten in der Lage sein, Objekt B als Objekt A zu zeigen. Von unten (Antwort) Beispiel zeigen Sie Hund als Tier und daher ist es Polymorphismus. Bei Überladung rufen Sie jedoch eine andere Methode auf, jedoch mit "demselben Namen". Wie kann das Polymorphismus sein? Daher ist "statische Bindung" der richtige Begriff, aber statischer Polymorphismus tritt nicht bei Überlastung auf.
Punith Raj
@PunithRaj Sie beziehen sich wahrscheinlich auf Subtyp-Polymorphismus . Es gibt eine andere Art namens Ad-hoc, die für Überladung gilt.
Kelvin

Antworten:

196

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:

class Calculation {  
  void sum(int a,int b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  

  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  // 30
    obj.sum(20,20);     //40 
  }  
}  

übergeordnetes Beispiel:

class Animal {    
   public void move(){
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {

   public void move() {
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal(); // Animal reference and object
      Animal b = new Dog(); // Animal reference but Dog object

      a.move();//output: Animals can move

      b.move();//output:Dogs can walk and run
   }
}
KhAn SaAb
quelle
6
Ich bin neu in Java, also nur neugierig, was ist das zugrunde liegende Konzept zwischen Animal reference but Dog object, warum können wir nicht verwenden Dog reference and dog object?
Pratyay
3
Im obigen Beispiel habe ich versucht, das Konzept des Polymorphismus zu zeigen. Wir können die Referenz und das Objekt derselben Klasse erstellen, aber wir können keine Methodenüberschreibung erreichen. bitte gehen Sie durch mit folgendem Beitrag: stackoverflow.com/questions/12159601/...
khan SAAB
Das Überladen von Methoden ist der Polymorphismus der Kompilierungszeit. ist der gleiche Weg. Überlastet der Konstruktor auch den Polymorphismus der Kompilierungszeit?
Gaali Prabhakar
29
  • 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

user1374
quelle
17

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).

Rachana
quelle
2
Diese Antwort ist voller Fehler: (1) Methodenüberladung ist kein dynamischer Polymorphismus. Es ist statischer Polymorphismus. (2) Statische Methoden werden niemals überschrieben, sie werden ausgeblendet / beschattet. (3) Private Methoden werden nicht "überschrieben". Sie werden niemals in erster Linie vererbt.
John Red
14

Die Bindung bezieht sich auf die Verknüpfung zwischen Methodenaufruf und Methodendefinition.

Dieses Bild zeigt deutlich, was bindend ist.

Bindung

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:

Statische Bindung ist eine Bindung, die während der Kompilierung auftritt. Es wird auch als frühe Bindung bezeichnet, da die Bindung erfolgt, bevor ein Programm tatsächlich ausgeführt wird

.

Die statische Bindung kann wie im folgenden Bild gezeigt werden.

Geben Sie hier die Bildbeschreibung ein

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:

Dynamische Bindung ist eine Bindung, die zur Laufzeit erfolgt. Es wird auch als späte Bindung bezeichnet, da die Bindung erfolgt, wenn das Programm tatsächlich ausgeführt wird.

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.

Geben Sie hier die Bildbeschreibung ein

Referenz statische Bindung und dynamische Bindung in Java

Elsayed
quelle
besser als vorher.
AnBisw
8

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.

public class DynamicBindingTest {

    public static void main(String args[]) {
        Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
        vehicle.start();       //Car's start called because start() is overridden method
    }
}

class Vehicle {

    public void start() {
        System.out.println("Inside start method of Vehicle");
    }
}

class Car extends Vehicle {

    @Override
    public void start() {
        System.out.println("Inside start method of Car");
    }
}

Ausgabe:

Innenstartmethode des Autos

Statischer Bindungs- / Kompilierungszeitpolymorphismus:

Welche Methode aufgerufen werden soll, wird nur zur Kompilierungszeit entschieden.

public class StaticBindingTest {

    public static void main(String args[])  {
       Collection c = new HashSet();
       StaticBindingTest et = new StaticBindingTest();
       et.sort(c);

    }

    //overloaded method takes Collection argument
    public Collection sort(Collection c){
        System.out.println("Inside Collection sort method");
        return c;
    }


   //another overloaded method which takes HashSet argument which is sub class
    public Collection sort(HashSet hs){
        System.out.println("Inside HashSet sort method");
        return hs;
    }

}

Ausgabe: Innerhalb der Sammlung sortieren Metho

loknath
quelle
8

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).

Sujith PS
quelle
* (Objekt zur Laufzeit erstellen und auf Heap gehen), sollte es Laufzeit haben
Treffen
7

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 :

Unterklassen einer Klasse können ihr eigenes eindeutiges Verhalten definieren und dennoch einige der gleichen Funktionen der übergeordneten Klasse gemeinsam nutzen

Ravindra Babu
quelle
Generally overloading won't be considered as polymorphism.Können Sie bitte auf diesen Punkt näher eingehen?
Prime
1
Dynamisches Binden und Überschreiben ist ein markanter Punkt für Polymorphismus
Ravindra babu
5

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 Mammalund eine HumanKlasse

class Mammal {
    public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}

class Human extends Mammal {

    @Override
    public void speak() { System.out.println("Hello"); }

    public void speak(String language) {
        if (language.equals("Hindi")) System.out.println("Namaste");
        else System.out.println("Hello");
    }

}

Ich habe die Ausgabe sowie den Bytecode der folgenden Codezeilen eingefügt

Mammal anyMammal = new Mammal();
anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V

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 .

Naresh Joshi
quelle
3

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.

Kulasangar
quelle
3

Polymorphismus bezieht sich auf die Fähigkeit eines Objekts, sich für denselben Auslöser unterschiedlich zu verhalten.

Statischer Polymorphismus (Polymorphismus zur Kompilierungszeit)

  • Der statische Polymorphismus entscheidet, welche Methode während der Kompilierungszeit ausgeführt werden soll.
  • Das Überladen von Methoden ist ein Beispiel für statischen Polymorphismus, und es ist erforderlich, dass statischer Polymorphismus auftritt.
  • Statischer Polymorphismus durch statische Bindung.
  • Statischer Polymorphismus tritt in derselben Klasse auf.
  • Für den statischen Polymorphismus ist keine Objektzuweisung erforderlich.
  • Vererbung für statischen Polymorphismus nicht beteiligt.

Dynamischer Polymorphismus (Laufzeitpolymorphismus)

  • Der dynamische Polymorphismus entscheidet, welche Methode zur Laufzeit ausgeführt werden soll.
  • Das Überschreiben von Methoden ist ein Beispiel für dynamischen Polymorphismus, und es ist erforderlich, dass dynamischer Polymorphismus auftritt.
  • Dynamischer Polymorphismus durch dynamische Bindung.
  • Dynamischer Polymorphismus tritt zwischen verschiedenen Klassen auf.
  • Dies ist erforderlich, wenn ein Unterklassenobjekt einem Superklassenobjekt für dynamischen Polymorphismus zugewiesen ist.
  • Vererbung für dynamischen Polymorphismus.
Saveendra Ekanayake
quelle
1

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.

Pavan Reddy
quelle
1

Betrachten Sie den folgenden Code:

public class X
{
    public void methodA() // Base class method
    {
        System.out.println ("hello, I'm methodA of class X");
    }
}

public class Y extends X
{
    public void methodA() // Derived Class method
    {
        System.out.println ("hello, I'm methodA of class Y");
    }
}
public class Z
{
public static void main (String args []) {

    //this takes input from the user during runtime
    System.out.println("Enter x or y");
    Scanner scanner = new Scanner(System.in);
    String value= scanner.nextLine();

    X obj1 = null;
    if(value.equals("x"))
        obj1 = new X(); // Reference and object X
    else if(value.equals("y"))
        obj2 = new Y(); // X reference but Y object
    else
        System.out.println("Invalid param value");

    obj1.methodA();
}
}

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.

user2048204
quelle
0

Das Überladen von Methoden ist ein Polymorphismus zur Kompilierungszeit. Nehmen wir ein Beispiel, um das Konzept zu verstehen.

class Person                                            //person.java file
{
    public static void main ( String[] args )
    {
      Eat e = new Eat();
       e.eat(noodle);                                //line 6
    }

   void eat (Noodles n)      //Noodles is a object    line 8                     
   {

   }
   void eat ( Pizza p)           //Pizza is a object
  {

  }

}

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.

Manoj Gururaj
quelle
0

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.

Lewis Kelsey
quelle