Qual è la differenza tra polimorfismo dinamico e statico in Java?


118

Qualcuno può fornire un semplice esempio che spieghi la differenza tra polimorfismo dinamico e statico in Java?


4
Le sostituzioni vengono talvolta definite "polimorfismo statico". Questo allunga un po 'le cose, ma è quello che sta succedendo.
dasblinkenlight

@dasblinkenlight grazie per le informazioni. c'è qualche esempio per questo ??
Prabhakar Manthena

Cerca "sovraccarico del metodo" e "sovrascrittura del metodo".
dasblinkenlight

5
Non capisco come il sovraccarico sia polimorfismo. Il polimorfismo è un concetto di oggetto. dovremmo essere in grado di mostrare l'oggetto B come oggetto A. dal basso (risposta) esempio che mostri Cane come un animale e quindi è polimorfismo. Ma in sovraccarico stai chiamando un metodo diverso ma con lo "stesso nome". Come può essere polimorfismo. Quindi "legame statico" è il termine corretto da usare, ma il polimorfismo statico non è in caso di sovraccarico.
Punith Raj

@PunithRaj Probabilmente ti riferisci al polimorfismo del sottotipo . C'è un altro tipo chiamato Ad hoc che si applica al sovraccarico.
Kelvin

Risposte:


196

Polimorfismo

1. Binding statico / binding in fase di compilazione / binding anticipato / sovraccarico del metodo (nella stessa classe)

2. Associazione dinamica / Associazione in fase di esecuzione / Associazione tardiva / Sostituzione del metodo (in classi diverse)

esempio di sovraccarico:

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 
  }  
}  

esempio prevalente:

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
   }
}

6
Sono nuovo in Java, quindi sono curioso di sapere qual è il concetto sottostante Animal reference but Dog object, perché non possiamo usarlo Dog reference and dog object?
pratyay

3
Nell'esempio sopra ho cercato di mostrare il concetto di polimorfismo. possiamo creare il riferimento e l'oggetto della stessa classe ma non possiamo ottenere l'override del metodo. si prega di andare fino in fondo al di sotto del messaggio: stackoverflow.com/questions/12159601/...
KhAn Saab

il sovraccarico del metodo è il polimorfismo in fase di compilazione. è lo stesso modo. è anche il sovraccarico del costruttore Compile time polimorfismo?
Gaali Prabhakar

29
  • Il sovraccarico del metodo sarebbe un esempio di polimorfismo statico

  • mentre l'override sarebbe un esempio di polimorfismo dinamico.

    Perché, in caso di sovraccarico, in fase di compilazione il compilatore sa quale metodo collegare alla chiamata. Tuttavia, è determinato in fase di esecuzione per il polimorfismo dinamico


17

Il polimorfismo dinamico (tempo di esecuzione) è il polimorfismo esistente in fase di esecuzione. Qui, il compilatore Java non capisce quale metodo viene chiamato al momento della compilazione. Solo JVM decide quale metodo viene chiamato in fase di esecuzione. Il sovraccarico del metodo e l'override del metodo utilizzando metodi di istanza sono esempi di polimorfismo dinamico.

Per esempio,

  • Considera un'applicazione che serializza e deserializza diversi tipi di documenti.

  • Possiamo avere "Documento" come classe base e diverse classi di tipi di documento che ne derivano. Ad esempio XMLDocument, WordDocument, ecc.

  • La classe Document definirà i metodi 'Serialize ()' e 'De-serialize ()' come virtuali e ogni classe derivata implementerà questi metodi a modo suo in base al contenuto effettivo dei documenti.

  • Quando è necessario serializzare / de-serializzare diversi tipi di documenti, gli oggetti del documento verranno indicati dal riferimento alla classe 'Document' (o puntatore) e quando vengono chiamati i metodi 'Serialize ()' o 'De-serialize ()' su di esso vengono chiamate le versioni appropriate dei metodi virtuali.

Il polimorfismo statico (tempo di compilazione) è il polimorfismo mostrato in fase di compilazione. Qui, il compilatore Java sa quale metodo viene chiamato. Override del metodo e override del metodo utilizzando metodi statici; l'override del metodo utilizzando metodi privati ​​o finali sono esempi di polimorfismo statico

Per esempio,

  • Un oggetto dipendente può avere due metodi print () uno che non accetta argomenti e uno che accetta una stringa di prefisso da visualizzare insieme ai dati del dipendente.

  • Date queste interfacce, quando il metodo print () viene chiamato senza alcun argomento, il compilatore, guardando gli argomenti della funzione, sa quale funzione deve essere chiamata e genera il codice oggetto di conseguenza.

Per maggiori dettagli leggi "Cos'è il polimorfismo" (Google it).


2
Questa risposta piena di errori: (1) Il sovraccarico del metodo non è polimorfismo dinamico. È polimorfismo statico. (2) I metodi statici non vengono mai sovrascritti, sono nascosti / ombreggiati. (3) I metodi privati ​​non vengono "sovrascritti". Non vengono mai ereditate in primo luogo.
John Red

15

Il binding si riferisce al collegamento tra la chiamata al metodo e la definizione del metodo.

Questa immagine mostra chiaramente cosa è vincolante.

rilegatura

In questa immagine, la chiamata "a1.methodOne ()" è vincolante alla corrispondente definizione di methodOne () e la chiamata "a1.methodTwo ()" è vincolante alla corrispondente definizione di methodTwo ().

Per ogni chiamata al metodo dovrebbe esserci una corretta definizione del metodo. Questa è una regola in java. Se il compilatore non vede la definizione del metodo corretta per ogni chiamata al metodo, genera un errore.

Ora, vieni al binding statico e dinamico in java.

Associazione statica in Java:

L'associazione statica è un'associazione che avviene durante la compilazione. Viene anche chiamato associazione anticipata perché l'associazione avviene prima che un programma venga effettivamente eseguito

.

Il legame statico può essere dimostrato come nell'immagine sottostante.

inserisci qui la descrizione dell'immagine

In questa immagine, 'a1' è una variabile di riferimento di tipo Classe A che punta all'oggetto di classe A. 'a2' è anche variabile di riferimento di tipo classe A ma punta all'oggetto di Classe B.

Durante la compilazione, durante l'associazione, il compilatore non controlla il tipo di oggetto a cui punta una particolare variabile di riferimento. Controlla semplicemente il tipo di variabile di riferimento attraverso il quale viene chiamato un metodo e controlla se esiste una definizione di metodo per esso in quel tipo.

Ad esempio, per la chiamata al metodo "a1.method ()" nell'immagine sopra, il compilatore controlla se esiste una definizione del metodo per method () nella classe A. Poiché 'a1 ′ è il tipo di classe A. Allo stesso modo, per la chiamata al metodo "a2.method ()", controlla se esiste una definizione di metodo per method () nella Classe A. Poiché 'a2 ′ è anche di tipo Classe A. Non controlla a quale oggetto puntano "a1" e "a2". Questo tipo di associazione è chiamata associazione statica.

Associazione dinamica in Java:

L'associazione dinamica è un'associazione che si verifica durante il runtime. Viene anche chiamato binding tardivo perché il binding avviene quando il programma è effettivamente in esecuzione.

Durante il tempo di esecuzione gli oggetti effettivi vengono utilizzati per l'associazione. Ad esempio, per la chiamata "a1.method ()" nell'immagine sopra, verrà chiamato method () dell'oggetto effettivo a cui punta 'a1'. Per la chiamata "a2.method ()", verrà chiamato method () dell'oggetto effettivo a cui punta 'a2'. Questo tipo di associazione si chiama associazione dinamica.

Il legame dinamico dell'esempio precedente può essere dimostrato come di seguito.

inserisci qui la descrizione dell'immagine

Riferimento static-binding-and-dynamic-binding-in-java


meglio di prima.
AnBisw

8

Polimorfismo: il polimorfismo è la capacità di un oggetto di assumere molte forme. L'uso più comune del polimorfismo in OOP si verifica quando un riferimento alla classe padre viene utilizzato per fare riferimento a un oggetto classe figlio.

Polimorfismo di binding dinamico / runtime:

Polimorfismo in fase di esecuzione noto anche come sostituzione del metodo. In questo meccanismo tramite il quale una chiamata a una funzione sottoposta a override viene risolta in fase di esecuzione.

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

Produzione:

Metodo di avvio interno dell'auto

Legame statico / polimorfismo in fase di compilazione:

Il metodo da chiamare viene deciso solo in fase di compilazione.

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

}

Output: metodo di ordinamento Inside Collection


8

il sovraccarico del metodo è un esempio di tempo di compilazione / polimorfismo statico perché l'associazione del metodo tra la chiamata al metodo e la definizione del metodo avviene in fase di compilazione e dipende dal riferimento della classe (il riferimento creato in fase di compilazione e va allo stack).

l'override del metodo è un esempio di polimorfismo in fase di esecuzione / dinamico perché l'associazione del metodo tra la chiamata al metodo e la definizione del metodo avviene in fase di esecuzione e dipende dall'oggetto della classe (oggetto creato in fase di esecuzione e va nell'heap).


* (oggetto creato in fase di esecuzione e va all'heap), dovrebbe essere eseguito in fase di esecuzione
Meet

7

In parole povere :

Polimorfismo statico : lo stesso nome del metodo è sovraccaricato con un tipo o un numero di parametri diversi nella stessa classe (firma diversa). La chiamata al metodo mirata viene risolta in fase di compilazione.

Polimorfismo dinamico : lo stesso metodo viene sostituito con la stessa firma in classi diverse . Il tipo di oggetto su cui il metodo viene richiamato non è noto in fase di compilazione ma verrà deciso in fase di esecuzione.

Generalmente il sovraccarico non sarà considerato come polimorfismo.

Dalla pagina del tutorial Java :

Le sottoclassi di una classe possono definire i propri comportamenti unici e tuttavia condividere alcune delle stesse funzionalità della classe genitore


Generally overloading won't be considered as polymorphism.puoi per favore approfondire questo punto.
Prime

1
Il binding dinamico e l'override sono un punto importante per il polimorfismo
Ravindra babu

5

Il sovraccarico del metodo è noto come polimorfismo statico e anche noto come polimorfismo a tempo di compilazione o binding statico perché le chiamate di metodo sovraccaricate vengono risolte in fase di compilazione dal compilatore sulla base dell'elenco di argomenti e del riferimento su cui stiamo chiamando il metodo.

E il Method Overriding è noto come Dynamic Polymorphism o simple Polymorphism o Runtime Method Dispatch o Dynamic Binding , perché chiamata di metodo override si risolvono in fase di esecuzione.

Per capire perché è così, facciamo un esempio di Mammaland Humanclass

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

}

Ho incluso l'output e il bytecode nelle righe di codice seguenti

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

E guardando il codice sopra possiamo vedere che i bytecode di humanMammal.speak (), human.speak () e human.speak ("Hindi") sono totalmente diversi perché il compilatore è in grado di differenziarli in base alla lista degli argomenti e riferimento alla classe. Ed è per questo che il Method Overloading è noto come Static Polymorphism .

Ma il bytecode per anyMammal.speak () e humanMammal.speak () è lo stesso perché secondo il compilatore entrambi i metodi sono chiamati su Mammal reference ma l'output per entrambi i metodi è diverso perché in fase di runtime JVM sa quale oggetto contiene un riferimento e JVM chiama il metodo sull'oggetto ed è per questo che il Method Overriding è noto come Dynamic Polymorphism.

Quindi dal codice e dal bytecode di cui sopra, è chiaro che durante la fase di compilazione il metodo di chiamata viene considerato dal tipo di riferimento. Ma al momento dell'esecuzione il metodo verrà chiamato dall'oggetto che contiene il riferimento.

Se vuoi saperne di più su questo puoi leggere di più su Come JVM gestisce internamente l'overload e l'override del metodo .


3

Polimorfismo statico: è dove la decisione di risolvere quale metodo realizzare, viene determinata durante il tempo di compilazione. Il sovraccarico del metodo potrebbe essere un esempio di questo.

Polimorfismo dinamico: è dove la decisione di scegliere quale metodo eseguire, viene impostata durante il runtime. Il metodo Overriding potrebbe essere un esempio di questo.


3

Il polimorfismo si riferisce alla capacità di un oggetto di comportarsi in modo diverso per lo stesso trigger.

Polimorfismo statico (polimorfismo in fase di compilazione)

  • Il polimorfismo statico decide quale metodo eseguire durante la fase di compilazione.
  • Il metodo Overloading è un esempio di polimorfismo statico, ed è necessario che si verifichi un polimorfismo statico.
  • Polimorfismo statico ottenuto tramite legame statico.
  • Il polimorfismo statico si verifica nella stessa classe.
  • L'assegnazione di oggetti non è richiesta per il polimorfismo statico.
  • Ereditarietà non coinvolta per il polimorfismo statico.

Polimorfismo dinamico (polimorfismo a runtime)

  • Il polimorfismo dinamico decide quale metodo eseguire in runtime.
  • Il metodo Overriding è un esempio di polimorfismo dinamico, ed è necessario che si verifichi un polimorfismo dinamico.
  • Polimorfismo dinamico ottenuto attraverso il legame dinamico.
  • Il polimorfismo dinamico si verifica tra classi diverse.
  • È necessario quando un oggetto di sottoclasse è assegnato a un oggetto di super classe per il polimorfismo dinamico.
  • Ereditarietà coinvolta per il polimorfismo dinamico.

1

Polimorfismo a tempo di compilazione (Static Binding / Early Binding): Nel polimorfismo statico, se chiamiamo un metodo nel nostro codice, la definizione di quel metodo da chiamare viene effettivamente risolta solo in fase di compilazione.

(o)

In fase di compilazione, Java sa quale metodo richiamare controllando le firme del metodo. Quindi, questo è chiamato polimorfismo in fase di compilazione o binding statico.

Polimorfismo dinamico (Late Binding / Runtime Polymorphism): in fase di esecuzione, Java attende fino al runtime per determinare quale oggetto è effettivamente puntato dal riferimento. La risoluzione del metodo è stata presa in fase di esecuzione, per questo che chiamiamo polimorfismo in fase di esecuzione.


1

Considera il codice seguente:

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

Ora, guardando il codice non puoi mai dire quale implementazione di methodA () verrà eseguita, perché dipende dal valore che l'utente fornisce durante il runtime. Quindi, viene deciso solo durante il runtime quale metodo verrà chiamato. Quindi, polimorfismo di runtime.


0

Il sovraccarico del metodo è un polimorfismo in fase di compilazione, facciamo un esempio per comprendere il concetto.

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 questo esempio, Persona ha un metodo di mangiare che rappresenta che può mangiare pizza o tagliatelle. Che il metodo eat sia sovraccarico quando compiliamo questo Person.java il compilatore risolve la chiamata al metodo "e.eat (noodles) [che si trova alla riga 6] con la definizione del metodo specificata nella riga 8 che è il metodo che accetta noodles come parametro e l'intero processo è fatto dal compilatore, quindi è il polimorfismo in fase di compilazione.Il processo di sostituzione della chiamata al metodo con la definizione del metodo è chiamato binding, in questo caso è fatto dal compilatore quindi è chiamato come binding anticipato.


0

Seguendo la risposta di Naresh, il polimorfismo dinamico è solo "dinamico" in Java a causa della presenza della macchina virtuale e della sua capacità di interpretare il codice in fase di esecuzione piuttosto che il codice in esecuzione in modo nativo.

In C ++ deve essere risolto in fase di compilazione se viene compilato in un binario nativo usando gcc, ovviamente; tuttavia, il salto di runtime e il thunk nella tabella virtuale sono ancora denominati "ricerca" o "dinamica". Se C eredita B e tu dichiari , c punterà già all'oggetto C esterno e il puntatore verrà passato a C :: method1 () nel segmento di testo. Fare riferimento a: http://www.programmersought.com/article/2572545946/B* b = new C(); b->method1(); , b sarà risolto dal compilatore per puntare a un oggetto B all'interno di C (per una classe semplice eredita una situazione di classe, l'oggetto B all'interno di C e C inizierà allo stesso indirizzo di memoria quindi niente è necessario che sia fatto; indicherà il vptr che entrambi usano). Se C eredita B e A, la tabella delle funzioni virtuali dell'oggetto A all'interno della voce C per il metodo1 avrà un thunk che sposterà il puntatore all'inizio dell'oggetto C incapsulante e quindi lo passerà al vero A :: metodo1 () nel segmento di testo che C ha sovrascritto. PerC* c = new C(); c->method1()

In java, for B b = new C(); b.method1();, la macchina virtuale è in grado di controllare dinamicamente il tipo di oggetto accoppiato con be può passare il puntatore corretto e chiamare il metodo corretto. Il passaggio aggiuntivo della macchina virtuale elimina la necessità di tabelle di funzioni virtuali o il tipo da risolvere in fase di compilazione, anche quando potrebbe essere noto in fase di compilazione. È solo un modo diverso di farlo, che ha senso quando è coinvolta una macchina virtuale e il codice viene compilato solo in bytecode.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.