domenica 28 settembre 2014

Ereditarietà

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

Nessun commento:

Posta un commento