I linguaggi orientati agli oggetti consentono l'ereditarietà dei tipi riferimento. Se un tipo eredita da un altro, ne prende tutti i membri. Ad un tipo si possono tuttavia aggiungere dei nuovi membri oppure riscriverne alcuni.
I tipi sono organizzati in una gerarchia.
Supponiamo di avere uno stack e di volerne contare gli elementi.
Potremmo riscrivere la classe con il metodo in più che esegue il conteggio, oppure utilizzare l’ereditarietà.
Stack<-Counting_Stack
Baso il nuovo tipo che mi serve sull’implementazione originale. I sottotipi (classi ereditate) possono avere dei sottotipi in più e ridefinire le funzioni virtuali.
Overwriting
Le classi possono ereditare i metodi dalle classi padri, ed utilizzarli senza problemi. A volte però vogliamo che una classe figlia si comporti in modo diverso dalla classe da cui eredita.
In questi casi possiamo “sovrascrivere” il metodo che ci interessa, nella nuova classe. In questo caso parliamo di “overwriting”.
Vediamo l'implementazione
using System; namespace Sample
{ public class Sample
{ public static void Main()
{ //start point
} /// <summary>
/// Classe base
/// </summary> private class Stack
{ //metodi della classe private Stack()
{ //costruttore base
}
} /// <summary>
/// Classe ereditata da Stack
/// </summary> private class Counting_Stack : Stack
{ //metodi della classe public Counting_Stack() :base()
{ //prende le funzionalità del metodo della classe padre
} //La funzionalità di conteggio elementi in più che volevamo public int contaElementi()
{ //implementazione
}
}
}
}
Classi Astratte ed Interfacce
Alcune classi sono disegnate per non avere direttamente delle istanze, ma perchè altre classi possano ereditarvi.
Una classe è astratta quando non può avere delle istanze dirette.
Una interfaccia è una classe che contiene soltanto dei metodi astratti, tuttavia pure essendo una classe va dichiarata con la parola chiave 'interface' e non class.
Una classe può implementare anche più di una interfaccia, in quel caso deve definirne tutti i metodi e darne una implementazione.
classi abstract
Una dichiarata 'abstract' non può essere istanziata, è realizzata esclusivamente per consentire l'ereditarietà.
classi sealed
Una classe 'sealed' non consente ad altre classi di ereditare da essa.
Classi Nidificate
La classi vengono in genere specificate una indipendente dall'altra. E' comunque possibile dichiarare una classe all'interno di un'altra. in questo caso parliamo di classi nidificate.
Esempio:
public class clDBTools
{ public class clDBConections
{ public clDBConections()
{ //costruttore;
}
} public clDBTools()
{ //costruttore;
}
}
Polimorfismo ed Overriding
Supponiamo di avere due classi "Quadrato" e "Triangolo" che ereditano entrambe dalla classe padre "Figura".
Suppponiamo inoltreche in Figura ci sia un metodo per calcolare l'area, e questo metodo debba essere utilizzato anche dalle istanze di quadrato e triangolo.
Possiamo utilizzare l'overriding per richiamare il metodo corretto in base al tipo di classe di cui abbiamo istanziato un oggetto.
In parole povere se stiamo lavorato con un triangolo, utilizzaremo il metodo della classe triangolo, se invece stiamo lavorando con un quadrato utilizzaremo il metodo della classe quadrato.
Esempio
using System; namespace Sample
{ public class Sample { public static void Main() { //quando creiamo un triangolo, utilizziamo il costruttore ereditato da figura triangolo t = new triangolo(1,3); //richiamo il metodo della classe triangolo t.calcolaArea(); quadrato q = new quadrato(1,3); q.calcolaArea(); } private class Figura { //Fields dell'oggetto Figura
//Vengono ereditati dagli oggetti figlio private double _Base; private double _Altezza; public double Base { get {return _Base;} } public double Altezza { get {return _Altezza;} } //metodi della classe public Figura(double Base, double Altezza) { this._Base = Base; this._Altezza = Altezza; } public virtual void calcolaArea() { //metodo della classe padre } } private class quadrato : Figura { public quadrato(double Base, double Altezza) :base(Base, Altezza) { Console.WriteLine("Questo è un quadrato"); //prende le funzionalità del metodo della classe padre
//per cui non necessitiamo di inizializzazione } public override void calcolaArea() { //metodo "overridden" Console.WriteLine("Area quadrato: " + Base*Altezza); } } private class triangolo : Figura { public triangolo(double Base, double Altezza) :base(Base, Altezza) { Console.WriteLine("Questo è un triangolo"); //prende le funzionalità del metodo della classe padre
//per cui non necessitiamo di inizializzazione } public override void calcolaArea() { //metodo "overridden" Console.WriteLine("Area triangolo: " + Base*Altezza/2); } } }
}
output
Questo è un triangolo
Area triangolo: 1,5
Questo è un quadrato
Area quadrato: 3