Ereditarietà multipla
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.
Problema del diamante
modificaL'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
modificaJava e .NET
modificaIn 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.
Dalla versione Java 8, tuttavia, si sono introdotti i modificatori "default" che se associati a metodi di interfacce permettono (al contrario dei metodi senza questo modificatore) non solo di dichiarare ma anche di implementare in modo differente gli stessi metodi nelle interfacce. È comunque d'obbligo l'override dei metodi nelle sottoclassi che implementano entrambe le interfacce, ma tramite un'istruzione ben definita si può invocare un preciso metodo implementato di una specifica interfaccia genitrice. Così nel caso del problema del diamante la classe D effettua l'override del metodo in comune a B e C definito in A e invoca lo specifico metodo di B o C.
C++
modificaC++ 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
modificaIn 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
modificaAnalogamente 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
modificaIn 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
modificaPython 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
modificaEcco 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
modificaCollegamenti esterni
modifica- (EN) Denis Howe, multiple inheritance, in Free On-line Dictionary of Computing. Disponibile con licenza GFDL
- (EN) Articolo di Jonathan Lurie di Builder.Com sull'ereditarietà multipla nei linguaggi della piattaforma .NET, su builder.com.com. URL consultato il 21 ottobre 2005 (archiviato dall'url originale il 12 gennaio 2006).
- Il problema del diamante su UML e ingegneria del software: dalla teoria alla pratica (da Google Libri)