Ereditarietà multipla
| Questa voce o sezione sull'argomento programmazione non cita le fonti necessarie o quelle presenti sono insufficienti. |
Alcuni linguaggi di programmazione permettono di utilizzare l'ereditarietà multipla, in cui una classe può ereditare funzionalità e caratteristiche da più di una classe base. Questa tecnica si contrappone all'ereditarietà singola, in cui una classe può ereditare da una, e solo una, classe base.
Nella programmazione orientata agli oggetti, l'ereditarietà descrive una relazione gerarchica fra due classi, nella quale una (quella che eredita) è chiamata "classe derivata" (o "classe figlia", o "sottotipo"), e l'altra (quella da cui si eredita) è chiamata "classe genitrice" (o "classe base", o "superclasse"). Le funzionalità ereditate dalla "figlia" permettono agli oggetti istanziati su di essa di condividere le funzionalità della "genitrice", cioè della classe base.
Per esempio: supponiamo di aver creato una classe:
Mammifero
dotata di funzionalità come mangiare, respirare, riprodursi, ecc.. Possiamo definire un'altra classe:
Topo
che eredita tutte le funzionalità di Mammifero senza doverle ridefinire, in quanto, essendo il topo un mammifero, ne condivide tutte le caratteristiche. A queste funzionalità la nuova classe ne aggiunge altre, possedute dai "topi" e non comuni a tutti i mammiferi, come, ad esempio raccogliere spazzatura. Oltre che avere le caratteristiche comuni a tutti i mammiferi, tuttavia, i topi condividono altre caratteristiche e funzionalità con altre "classi" di oggetti, come, ad esempio:
Personaggi di Ratatouille oppure Vettori di malattie mortali
Quindi è molto comodo, per la classe Topo, poter ereditare anche le caratteristiche e le funzionalità di queste classi, senza doverle ridefinire.
Indice
Problema del diamante[modifica | modifica wikitesto]
L'ereditarietà multipla può essere causa, in alcuni contesti, di qualche confusione, tanto che alcuni ritengono che gli inconvenienti siano maggiori dei benefici.
Una possibile causa di ambiguità è la seguente: se due classi B e C ereditano dalla classe A e la classe D eredita sia da B che da C, se un metodo in D chiama un metodo definito in A, da quale classe viene ereditato?
Tale ambiguità prende il nome di problema del diamante (in inglese diamond problem), a causa della forma del diagramma di ereditarietà delle classi, simile ad un diamante.
Differenti linguaggi di programmazione hanno risolto quest'inconveniente in modi diversi.
Implementazione in alcuni linguaggi[modifica | modifica wikitesto]
Java e .NET[modifica | modifica wikitesto]
In Java si è adottato questo compromesso: una classe può ereditare le interfacce da più di una classe base - cioè esporre all'esterno gli stessi metodi delle interfacce delle classi base - ma può ereditare i dati ed i metodi effettivi da una sola classe base. Anche i linguaggi della piattaforma Microsoft .NET, come C# e Visual Basic utilizzano lo stesso approccio.
C++[modifica | modifica wikitesto]
C++ per default segue ogni percorso di ereditarietà separatamente, quindi l'oggetto D contiene due separati oggetti di A e gli usi dei membri di A devono essere opportunamente qualificati. Se l'ereditarietà da A a B e l'ereditarietà da A a C sono entrambe segnate come "virtual" ("class B : virtual A"), C++ si prende particolare cura di creare solo un oggetto A, l'utilizzo dei membri di A funziona correttamente. Se l'ereditarietà virtuale e l'ereditarietà non virtuale sono mischiate, esiste solo un A virtuale e un A non virtuale per ogni percorso di ereditarietà non virtuale a A.
Eiffel[modifica | modifica wikitesto]
In Eiffel le classi derivate adattano le funzionalità ereditate rinominandole o definendo anticipatamente le regole per risolvere le ambiguità e decidere quale versione applicare (quella ereditata o quella della classe base).
REALbasic[modifica | modifica wikitesto]
Analogamente a Java anche in REALbasic si possono ereditare metodi e dati da una sola classe base, e, in più, sono previsti metodi aggiuntivi per "estendere" le funzionalità di una classe senza dover ricorrere all'ereditarietà.
Perl[modifica | modifica wikitesto]
In Perl le classi da cui ereditare sono disposte in una lista ordinata, e viene poi chiamato il primo metodo trovato in ordine gerarchico di profondità della prima classe della lista, e così di seguito per le classi successive e per le loro rispettive classi base.
Python[modifica | modifica wikitesto]
Python supporta una forma di ereditarietà multipla, e viene chiamato un metodo attraverso la regola prima-in-profondità, da-sinistra-a-destra. Perciò, se un attributo non viene trovato nella classe derivata, viene cercato nella prima classe base, poi (ricorsivamente) nelle classi base di quest'ultima e, solo se non vi è stato trovato, viene ricercato nella seconda classe base della classe derivata, e così via.
Esempio[modifica | modifica wikitesto]
Ecco un esempio di ereditarietà multipla in C++:
class A
{
protected:
int i;
public:
int get_i() {return i;}
void set_i(int n) {i=n;}
};
class B
{
protected:
int j;
public:
int get_j() {return j;}
void set_j(int n) {j=n;}
};
class C : public A, public B
{
protected:
int k;
public:
int get_k() {return k;}
void set_k(int n) {k=n;}
};
In questo caso, C erediterà sia da A che da B, ed avrà quindi le variabili d'istanza i e j e le funzioni get_i, set_i, get_j e set_j, oltre che a k ed a get_k ed a set_k.
Voci correlate[modifica | modifica wikitesto]
- Classe (informatica)
- Classe astratta (informatica)
- Ereditarietà (informatica)
- Incapsulamento (informatica)
- Interfaccia (informatica)
- Oggetto (informatica)
- Polimorfismo (informatica)
- Programmazione orientata agli oggetti