Qual è la differenza principale tra eredità e polimorfismo?


172

Oggi mi è stata presentata questa domanda in un esame di fine libro aperto e mi sono ritrovato perso. Stavo leggendo Head first Javaed entrambe le definizioni sembravano essere esattamente le stesse. Mi stavo solo chiedendo quale fosse la differenza PRINCIPALE per il mio pensiero. So che ci sono una serie di domande simili a questa, ma nessuna delle quali ho visto che fornisce una risposta definitiva.


2
In qualche modo correlato a questa domanda: il polimorfismo è possibile senza eredità
Edwin Dalorzo,

Risposte:


289

L'ereditarietà è quando una "classe" deriva da una "classe" esistente. Quindi se hai una Personclasse, allora hai una Studentclasse che si estende Person, Student eredita tutte le cose che Personha. Ci sono alcuni dettagli sui modificatori di accesso che metti nei campi / metodi in Persona, ma questa è l'idea di base. Ad esempio, se hai un campo privato attivo Person, Studentnon lo vedrà perché i suoi campi privato e privato non sono visibili alle sottoclassi.

Il polimorfismo si occupa di come il programma decide quali metodi usare, a seconda del tipo di cosa che ha. Se hai un Person, che ha un readmetodo e hai un Studentche si estende Person, di cui ha una propria implementazione read, quale metodo viene chiamato viene determinato dal runtime, a seconda che tu abbia a Persono a Student. Diventa un po 'complicato, ma se fai qualcosa del genere

Person p = new Student();
p.read();

viene chiamato il metodo read su Student . Questo è il polimorfismo in azione. Puoi fare quel compito perché a Student è a Person , ma il runtime è abbastanza intelligente da sapere che il tipo effettivo di pè Studente .

Si noti che i dettagli differiscono tra le lingue. Ad esempio, puoi fare l'ereditarietà in javascript, ma è completamente diverso dal modo in cui funziona in Java.


9
@ hvgtcodes quindi, in poche parole, la relazione superclasse-sottoclasse è ereditarietà e il concetto di implementazione dello stesso metodo in modo diverso tra la classe genitore e le sue sottoclassi, e chiamarli basati sulla situazione sono polimorfismo. Ho ragione?
Muhammad Raihan Muhaimin,

1
@hvgotcodes ma indica se Personil readmetodo utilizza il modificatore di accesso pubblico, gli Studentoggetti non saranno in grado di accedervi? e poi Student s = new Student();non sarà più facile? Non riesco ancora a ottenere i benefici del polimorfismo.
Scorpiorian83,

1
@hvgotcodes Student s = new Student () funzionerebbe. Ma diciamo dopo aver scritto molto del codice usando questa idea, e in seguito ti rendi conto di aver fatto un errore. La persona in realtà non è uno studente, è un insegnante. Quindi potresti semplicemente cambiare da Persona p = nuovo Studente () in Persona p = nuovo Insegnante (), quindi ti renderà la vita molto più semplice.
munmunbb,

La mia domanda qui sarebbe perché dovresti usare Person p = new Student();invece di Student p = new Student();?
PerfectContrast,

@PerfectContrast Penso che sia utile quando vuoi avere uno studente, un autista, un insegnante ecc. Come Persona e li raggruppi in un Elenco o qualcosa del genere. Quindi quando chiami "leggi" per tutti, tutti chiamano il loro metodo "leggi".
savante

205

L'ereditarietà si riferisce all'utilizzo della struttura e del comportamento di una superclasse in una sottoclasse.

Il polimorfismo si riferisce al cambiamento del comportamento di una superclasse nella sottoclasse.


5
Questa risposta implica che il polimorfismo richiede ereditarietà?
jaco0646,

6
@ jaco0646 - Nel contesto di Java, penso di si. (In altre lingue, forse non così tanto.) Nota che "superclasse" e "sottoclasse" sono usati qui liberamente. Il polimorfismo potrebbe anche significare l'ereditarietà del comportamento specificato (ma non implementato) in un'interfaccia.
Ted Hopp,

1
@AlirezaRahmani - Non capisco il tuo commento. Vuoi dire che l'ereditarietà non implica ereditare proprietà e comportamento? Ciò sarebbe contrario al modo in cui Java (e la maggior parte dei linguaggi orientati alla classe e orientati agli oggetti) definiscono l'ereditarietà. Dalla specifica del linguaggio Java, §8.4.8 : "Una classe C eredita dalla sua superclasse diretta tutti i metodi concreti m(entrambi statice instance) della superclasse per i quali ..." (seguiti da dettagli sull'ereditarietà). Mi sembra "riutilizzo del codice".
Ted Hopp,

L'ereditarietà di @TedHopp è principalmente uno strumento polimorfico, ma alcune persone, con molto ritardo, tentano di usarlo come un modo per riutilizzare / condividere il codice. La logica è "bene se eredito allora ottengo tutti i metodi gratuitamente", ma ignorando il fatto che queste due classi potenzialmente non hanno alcuna relazione polimorfica.
Alireza Rahmani Khalili il

1
@AlirezaRahmani - In Java (che è ciò di cui l'OP ha specificamente chiesto, secondo i tag), l'ereditarietà delle classi implica sicuramente l'ereditarietà del comportamento. Fa parte della definizione della lingua. Il fatto che questo possa essere usato in modo improprio mentre descrivi è uno dei punti deboli di Java. (Una debolezza correlata riguardava la dichiarazione delle classi per implementare le interfacce semplicemente per importare le costanti definite nell'interfaccia. Alla fine i progettisti Java introdussero import staticper eliminare questo uso improprio delle interfacce.) Per il polimorfismo puro in Java, lo strumento da usare sono interfacce, non ereditarietà di classe.
Ted Hopp,

63

Polimorfismo : la capacità di trattare oggetti di diverso tipo in modo simile. Esempio: la giraffa e il coccodrillo sono entrambi animali e gli animali possono farlo Move. Se hai un'istanza di un Animalallora puoi chiamare Movesenza sapere o preoccuparti di che tipo di animale sia.

Ereditarietà : questo è un modo per ottenere sia il polimorfismo che il riutilizzo del codice contemporaneamente.

Altre forme di polimorfismo : esistono altri modi per ottenere il polimorfismo, come le interfacce, che forniscono solo polimorfismo ma nessun riutilizzo del codice (a volte il codice è abbastanza diverso, come Moveper un serpente sarebbe abbastanza diverso da Moveper un cane, nel qual caso un'interfaccia sarebbe la scelta polimorfica migliore in questo caso.

In altri linguaggi dinamici il polimorfismo può essere ottenuto con Duck Typing, ovvero le classi che non hanno nemmeno bisogno di condividere la stessa classe o interfaccia di base, hanno solo bisogno di un metodo con lo stesso nome. O ancora più dinamico come Javascript, non hai nemmeno bisogno di classi, solo un oggetto con lo stesso nome di metodo può essere usato polimorficamente.


17

La differenza principale è che il polimorfismo è un risultato specifico dell'eredità. Il polimorfismo è il punto in cui il metodo da invocare viene determinato in fase di esecuzione in base al tipo di oggetto. Questa è una situazione che si verifica quando una classe eredita da un'altra e ignora un metodo particolare. Tuttavia, in un normale albero ereditario, non è necessario sovrascrivere alcun metodo e pertanto non tutte le chiamate a metodi devono essere polimorfiche. Ha senso? È un problema simile a tutti i veicoli Ford che sono automobili, ma non tutte le automobili sono Ford (anche se non del tutto ...).

Inoltre, il polimorfismo si occupa dell'invocazione del metodo mentre l'ereditarietà descrive anche i membri dei dati, ecc.


12

In Java, i due sono strettamente correlati. Questo perché Java utilizza una tecnica per l'invocazione del metodo chiamata "invio dinamico". Se ho

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

Poi vediamo che eredita B spinda A. Tuttavia, quando cerchiamo di manipolare l'oggetto come se fosse di tipo A, ancora otteniamo il comportamento di B per draw. Il drawcomportamento è polimorfico.

In alcune lingue, il polimorfismo e l'eredità non sono così strettamente correlati. In C ++, ad esempio, le funzioni non dichiarate virtuali vengono ereditate, ma non verranno inviate in modo dinamico, quindi non si otterrà quel comportamento polimorfico anche quando si utilizza l'ereditarietà.

In JavaScript, ogni chiamata di funzione viene inviata in modo dinamico e si ha una digitazione debole. Ciò significa che potresti avere un mucchio di oggetti non correlati, ognuno con il proprio draw, avere una funzione che scorre su di essi e chiamerebbe la funzione, e ognuno si comporterebbe perfettamente. Avresti il ​​tuo disegno polimorfico senza bisogno di eredità.


12

Polimorfismo: supponiamo che lavori per un'azienda che vende penne. Quindi fai una lezione molto bella chiamata "Penna" che gestisce tutto ciò che devi sapere su una penna. Scrivi tutti i tipi di classi per la fatturazione, la spedizione, la creazione di fatture, il tutto utilizzando la classe Pen. Arriva un capo giorno che dice "Grandi notizie! La società sta crescendo e ora stiamo vendendo libri e CD!" Non ottime notizie perché ora devi cambiare ogni classe che usa Pen per usare anche Book & CD. E se avessi originariamente creato un'interfaccia chiamata "SellableProduct" e Pen avesse implementato questa interfaccia. Quindi potresti aver scritto tutte le tue classi di spedizione, fatturazione, ecc. Per utilizzare quell'interfaccia invece di Pen. Ora tutto ciò che dovresti fare è creare una nuova classe chiamata Book & CompactDisc che implementa l'interfaccia SellableProduct. A causa del polimorfismo, tutte le altre classi potrebbero continuare a lavorare senza cambiamenti! Ha senso?

Quindi, significa usare l'ereditarietà che è uno dei modi per raggiungere il polimorfismo.

Il polimorfismo può essere possibile in una classe / interfaccia ma l'ereditarietà sempre tra 2 o più classi / interfacce. L'ereditarietà si conforma sempre alla relazione "is-a" mentre non è sempre con il polimorfismo (che può conformarsi sia alla relazione "is-a" / "has-a".


6

L'ereditarietà è più una cosa statica (una classe ne estende un'altra) mentre il polimorfismo è una cosa dinamica / di runtime (un oggetto si comporta in base al suo tipo dinamico / runtime e non al suo tipo statico / di dichiarazione).

Per esempio

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

-> Sebbene il tipo statico / di dichiarazione di a sia A, il tipo dinamico / di runtime effettivo è B e quindi a.foo () eseguirà foo come definito in B non in A.


3

Il polimorfismo è un approccio per esprimere il comportamento comune tra tipi di oggetti che hanno tratti simili. Inoltre, consente di creare varianti di tali tratti mediante l'override. L'ereditarietà è un modo per raggiungere il polimorfismo attraverso una gerarchia di oggetti in cui gli oggetti esprimono relazioni e comportamenti astratti. Tuttavia, non è l'unico modo per ottenere il polimorfismo. Il prototipo è un altro modo per esprimere il polimorfismo che è diverso dall'eredità. JavaScript è un esempio di un linguaggio che utilizza il prototipo. Immagino che ci siano anche altri modi.


3

L'ereditarietà è un concetto correlato al riutilizzo del codice. Ad esempio, se ho una classe genitore dire Animale contiene determinati attributi e metodi (per questo esempio dire makeNoise()e sleep()) e creo due classi figlio chiamate Doge Cat. Poiché sia ​​i cani che i gatti vanno a dormire nello stesso modo (suppongo) non è necessario aggiungere più funzionalità al sleep()metodo nelle sottoclassi Doge Catfornite dalla classe genitore Animal. Tuttavia, Dogabbaia e Catmiagola così anche se ilAnimalla classe potrebbe avere un metodo per emettere un rumore, un cane e un gatto emettono rumori diversi l'uno rispetto all'altro e agli altri animali. Pertanto, è necessario ridefinire tale comportamento per i loro tipi specifici. Da qui la definizione di polimorfismo. Spero che questo ti aiuti.


3

La documentazione di Oracle riportava esattamente la differenza.

eredità: una classe eredita campi e metodi da tutte le sue superclassi, dirette o indirette. Una sottoclasse può ignorare i metodi che eredita oppure può nascondere campi o metodi che eredita . (Notare che nascondere i campi è generalmente una cattiva pratica di programmazione.)

polimorfismo: il polimorfismo si riferisce a un principio in biologia in cui un organismo o una specie può avere molte forme o fasi diverse. Questo principio può essere applicato anche alla programmazione orientata agli oggetti e ai linguaggi come il linguaggio Java. Le sottoclassi di una classe possono definire i propri comportamenti unici e tuttavia condividere alcune delle stesse funzionalità della classe genitore.

il polimorfismo non è applicabile per i campi.

Post correlato:

Polimorfismo vs Override vs Overloading


1

Il polimorfismo è un effetto dell'eredità . Può succedere solo in classi che si estendono a vicenda. Ti consente di chiamare i metodi di una classe senza conoscere il tipo esatto della classe. Inoltre, il polimorfismo si verifica in fase di esecuzione .

Ad esempio, esempio di polimorfismo Java:

inserisci qui la descrizione dell'immagine

L'ereditarietà consente alle classi derivate di condividere interfacce e codice delle loro classi base. Succede in fase di compilazione .

Ad esempio, Tutte le classi nella piattaforma Java sono discendenti di oggetti (immagine per gentile concessione di Oracle):

inserisci qui la descrizione dell'immagine

Per saperne di più sull'eredità di Java e sul polimorfismo di Java


0

L'ereditarietà è quando la classe A eredita tutti i metodi / campi protetti / pubblici non statici da tutti i suoi genitori fino all'oggetto.


0

Se usi JAVA è semplice come questo:

Il polimorfismo sta usando metodi ereditati ma "scavalcandoli" per fare qualcosa di diverso (o lo stesso se chiami super, quindi tecnicamente non sarebbe polimorfico).

Correggimi se sbaglio.


0

Lo scopo principale del polimorfismo : creare una variabile di riferimento in superclasse e contenere la sottoclasse object => un oggetto può eseguire comportamenti multipli .

In eredità , la sottoclasse eredita le proprietà della superclasse .


0

l'ereditarietà è una specie di polimorfismo, in realtà l'ereditarietà è il polimorfismo dinamico. Quindi, quando rimuovi l'eredità non puoi più sovrascrivere.


0

Con Inheritance l'implementazione è definita nella superclasse, quindi il comportamento viene ereditato.

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

Con Polymorphism l'implementazione è definita nella sottoclasse, quindi solo l' interfaccia viene ereditata.

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

Il polimorfismo è ottenuto da Eredità in Java.

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

Hamsterclasse eredita la struttura da Animal, Herbivoree Petper esporre comportamentismo polimorfico di un animale domestico.

Catclasse eredita la struttura da Animal, Carnivoreed Petesporre anche comportamentismo polimorfa di un animale domestico.

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.