Il concetto di Ereditarietà Informatica
In informatica l'ereditarietà è uno dei concetti
fondamentali, essa costituisce infatti il secondo principio fondamentale della
programmazione ad oggetti.
In generale si può definire come un meccanismo che consente
di creare nuove classi che siano basate su altre già definite in precedenza; a
seconda del linguaggio di programmazione, l'ereditarietà può essere ereditarietà
singola o semplice (ogni classe può avere al più una superclasse diretta) o
multipla (ogni classe può avere più superclassi dirette).
Concetto di ereditarietà nel mondo reale:
È semplice poter osservare esempi di ereditarietà nel mondo
reale. Ad esempio, esistono al mondo centinaia di tipologie diverse di mammiferi:
cani, gatti, uomini, balene e così via. Ognuna di tali tipologie di mammiferi
possiede alcune caratteristiche che sono strettamente proprie (ad esempio,
soltanto l’uomo è in grado di parlare) mentre esistono, d’altra parte,
determinate caratteristiche che sono comuni a tutti i mammiferi (ad esempio, tutti
i mammiferi hanno il sangue caldo e nutrono i loro piccoli).
Nel mondo Object Oriented, potremmo riportare tale esempio
definendo un oggetto Mammifero che inglobi tutte le caratteristiche comuni ad
ogni mammifero. Da esso, poi, deriverebbero gli altri oggetti figlio: Cane,
Gatto, Uomo, Balena, etc.
L’oggetto cane, per citarne uno, erediterà, quindi, tutte le
caratteristiche dell’oggetto mammifero ma a sua volta conterrà delle
caratteristiche aggiuntive, distintive di tutti i cani come ad esempio: ringhiare
o abbaiare.
Il paradigma OOP, ha quindi carpito l’idea dell’ereditarietà
dal mondo reale e lo stesso concetto viene applicato ai sistemi software che
utilizzano tale tecnologia.
Come possiamo passare l’eredità da padre a figlio?
Abbiamo parlato di Classe Padre e Classe Figlio,
l’ereditarietà consente alla classe Figlio di ereditare ogni membro della
classe Padre, e poi aggiungere e modificare le cose secondo le nuove
funzionalità da realizzare. Avendo la necessità di utilizzare tutti i membri di
una classe padre senza doverli dichiarare di nuovo, ci basterà mettere una sola
dichiarazione nell'header della classe figlio:
class pesce_rosso : public pesce
{
...
};
In tal caso, la classe derivata si chiama pesce_rosso. La
classe base ha visibilità pubblica e si chiama pesce.
*!* Quando una classe eredita da un'altra, ne eredita tutti
i membri. Questo porta a due problemi:
proteggere i membri di una classe in modo che i suoi
potenziali figli non siano in grado di accederli.
far sì che una classe figlia impedisca l'accesso da parte
del mondo esterno alla parte ereditata dalla sua classe padre.
Ereditarietà privata, protetta o pubblica:
Il meccanismo di ereditarietà, pur essendo abbastanza
semplice, richiede una certa attenzione per non cadere in errori perchè dipende
dallo standard della classe base.
Gli attibuti ed i membri che vengono ereditati dalla classe
base possono cambiare la loro visibilità nella classe figlio, in base allo
specificatore/modificatore d’accesso con il quale si esegue l’ereditarietà
stessa, nel dettaglio:
Se lo specificatore d’accesso è public:
i public restano public
i protected restano protected
i private non possono essere
trasferiti
Se lo specificatore d’accesso è private:
i public diventano private
i protected diventano private
i private non possono essere
trasferiti
Se lo specificatore d’accesso è protected:
i public diventano protected
i protected restano protected
i private non possono essere
trasferiti
Tabella riassuntiva:
*!* Durante l’ereditarietà un accesso può restringersi o
restare uguale ma mai ampliarsi.
Esempio di codice:
#include
<iostream>
using
namespace std;
class persona{ //dichiarazione della classe persona
public: // con public rendo
i metodi accessibili dal main()
persona(); //costruttore senza passaggio di parametri
~persona(); //distruttore
void
visualizzaAnagrafica(); //metodo per visualizzare dati Anagrafica
char
nome[15]; //dichiarazione
stringa nome
char
cognome[15]; //dichiarazione
stringa cognome
int eta; //dichiarazione
variabile eta
};
persona::persona() //definizione del costruttore senza passaggio di parametri
{
cout <<" Inserisci Nome: ";
cin >> nome; //salvo l'input da utente nella stringa nome
cout << endl <<" Inserisci Cognome: ";
cin >> cognome;
//salvo l'input da utente nella stringa cognome
cout << endl <<" Inserisci eta': ";
cin >> eta; //salvo l'input da utente nella variabile eta
cout << endl;
}
class personaEstipendio : public persona { //creo Classe
Figlio personaEstipendio da Classe Padre persona con metodo "public"
public:
personaEstipendio(); //costruttore personaestipendio senza passaggio di parametri
~personaEstipendio(); //distruttore
void
visualizzaLavorativa(); //metodo per visualizzare dati Lavorativi
private:
char
tipoContratto[15];
int
importoStipendio;
};
personaEstipendio::personaEstipendio() //definizione del costruttore
senza passaggio di parametri
{
cout <<" Inserisci il tipo di contratto
lavorativo: ";
cin >> tipoContratto;
//salvo l'input da utente nella stringa
tipoContratto
cout << endl <<" Inserisci importo
stipendio: ";
cin >> importoStipendio; //salvo l'input da
utente nella variabile importoStipendio
}
void persona::visualizzaAnagrafica() //definizione
metodo visualizza della Classe Padre
{ cout << endl << " Dati dipendente:
"<< nome <<" - " <<cognome <<" -
" <<eta <<endl; //visualizzo i dati inseriti dall'utente
}
void personaEstipendio::visualizzaLavorativa() //definizione
metodo visualizza della Classe Figlio
{ cout <<" Dati Contratto: tipo di Contratto
"<< tipoContratto <<" Importo percepito "
<<importoStipendio <<endl; //visualizzo i dati inseriti dall'utente
}
persona :: ~persona()
//definizione del distruttore per comprendere
funzionamento
{
cout <<
"sono il distruttore Padre";
}
personaEstipendio :: ~personaEstipendio() //definizione del
distruttore per comprendere funzionamento
{
cout <<
"sono il distruttore Figlio";
}
main()
{
char menu;
do{
cout <<
"PROVE DI EREDITARIETA':\nData una Classe Padre con dati anagrafici
persona si crei una Classe Figlio \nche contenga anche dati lavorativi";
cout << endl
<< endl;
cout <<
"Inserimento da istanza oggetto Padre:";
cout << endl
<< endl;
persona
anagrafica; //istanzio
l'oggetto anagrafica di classe Padre tramite costruttore senza passaggio di
parametri
cout <<
"Inserimento da istanza oggetto Figlio:";
cout << endl
<< endl;
personaEstipendio
lavorativa; //istanzio
l'oggetto lavorativa di classe Figlio tramite costruttore senza passaggio di
parametri
cout << endl;
cout <<
"Visualizzo oggetto PADRE:";
cout << endl;
anagrafica.visualizzaAnagrafica();
//chiamata al metodo visualizza dell'oggetto
Padre anagrafica
cout << endl;
cout <<
"Visualizzo oggetto FIGLIO:";
cout << endl;
lavorativa.visualizzaAnagrafica(); //chiamata al
metodo visualizzaAnagrafica dell'oggetto Figlio
lavorativa.visualizzaLavorativa();
//chiamata al metodo visualizzaLavorativa
dell'oggetto Figlio
cout << endl;
cout <<
"Vuoi ripetere il programma? ";
cout <<
endl;
cin >>
menu;
}while((menu=='s')||(menu=='S'));
//se l'utente non vuole ripetere il programma,
fine
cout << endl << endl << endl;
return 0;
}
Fonti:
Lezione Prof. Alemanno - ITIS Molinari Milano
Schemi e Codice - Giacomo Marchesi
Nessun commento:
Posta un commento