Ereditarietà

17 marzo 2006

L’ereditarietà è uno dei concetti base della programmazione orientata agli oggetti. Si definisce ereditarietà la possibilità per una classe (detta classe derivata) di ereditare da un’altra (la classe base) le variabili, i metodi, le proprietà e di estendere il concetto della classe base e specializzarlo.

Tornando all’esempio delle automobili potremmo avere come classi derivate da automobili le sottoclassi: «auto con cambio manuale» e «auto con cambio automatico». Entrambe le sottoclassi ereditano tutte le proprietà e i comportamenti della classe base ma specializzano il modo di cambiare le marce.

Tutte le classi del Framework .NET ereditano implicitamente dalla classe base Object. In C# la relazione di ereditarietà tra le classi si esprime usando i due punti (:) che equivalgono a Inherits di VB.NET .

Riprendiamo una parte della classe Persona che abbiamo realizzato in precedenza:

public class Persona
{
  string mNome;
  protected string mCognome;

  public Persona(string Nome, string Cognome)
  {
    mNome = Nome;
    mCognome = Cognome;
  }

  public string Nome
  {
    get { return mNome; } set { mNome = value; }
  }

  //...
}

Osserviamo che la variabile mCognome è stata dichiarata come protected. Vogliamo ora definire un nuovo concetto, quello di Studente, ovvero una Persona dotata di un numero di matricola. Per fare questo, Studente deve ereditare da Persona (si può dire anche che Studente estende Persona):

public class Studente : Persona
{
  private int mMatricola;

  public Studente(string Nome, string Cognome, int Matricola)
  : base(Nome, Cognome)
  {
    mMatricola = Matricola;
  }

  public int Matricola
  {
    get { return mMatricola; }
    set { mMatricola = value; }
  }
}

Avendo definito questa relazione, nella classe Studente è possibile utilizzare tutto ciò che in Persona è stato definito come public, protected o internal, sia esso una variabile, una routine o una proprietà.

Ad esempio, all’interno di Studente è possibile utilizzare la variabile mCognome, che in Persona è definita protected, mentre mNome non è visibile, poiché il modificatore di accesso predefinito è private.

Esaminiamo il frammento

: base(Nome, Cognome)

subito dopo il costruttore di Studente. Esso richiama il costruttore della classe base passandogli gli argomenti specificati: in questo modo è possibile impostare le variabili mNome e mCognome della classe Persona sugli stessi valori passati al costruttore di Studente.

Se avessimo voluto che il nome della persona, indipendentemente da quanto indicato nel costruttore di Studente, fosse sempre “Pippo”, mentre il cognome fosse quello passato, sarebbe stato sufficiente scrivere:

: base("Pippo", Cognome)

Questo costrutto è necessario perché, quando si crea un oggetto di una classe che deriva da un’altra, prima del costruttore della classe derivata viene richiamato quello della classe base: nel nostro esempio, quando si istanzia un oggetto di tipo Studente, viene richiamato prima il costruttore della classe Persona, e, in seguito, quello di Studente.

Poiché la classe Persona non ha un costruttore senza argomenti, bisogna indicare esplicitamente tramite la parola chiave «base» quale costruttore richiamare. Se invece Persona avesse avuto un costruttore privo di argomenti, «base» non sarebbe servita.

Oltre che a questo scopo, «base» serve, in generale, per avere accesso ai metodi, alle variabili ed alle proprietà della classe che si sta derivando. Il corrispondente di «base» in Visual Basic è la parola chiave MyBase.

Provando a dichiarare oggetti di tipo Persona e Studente, si ottiene quanto segue:

Studente stud = new Studente("Marco", "", 0); 

stud.Matricola = 232440; 
// Corretto: Matricola è una property della classe Studente

stud.Cognome = "Minerva"; 
// Corretto: Cognome è una property ereditata da Persona
Persona pers = new Persona("Marco", "");

pers.Cognome = "Minerva";
// Corretto: Cognome è una property della classe Persona

pers.Matricola = 232440; 
// Errato: la property Matricola non è visibile da Persona

Senza le istruzioni : Persona e : base(Nome, Cognome) nella classe Studente, eliminiremmo l’ereditarietà e otterremmo un messaggio di errore relativo all’istruzione:

stud.Cognome = "Minerva"

Cliccare qui per scaricare le due classi Persona e Studente.

Grazie all’ereditarietà, dove è previsto l’uso di una certa classe, è quasi sempre possibile utilizzare una classe derivata. Questo è, probabilmente, uno degli aspetti più interessanti dell’ereditarietà.

Per esempio, supponiamo di avere una funzione che, ricevuti come argomenti due oggetti di tipo Persona, restituisce true se i loro nomi sono uguali:

public static bool NomiUguali(Persona p1, Persona p2)
{
  return (p1.Nome == p2.Nome);
}

Come argomenti a questa funzione, possono essere passati sia istanze della classe Persona, sia istanze di tutte le classi che ereditano da Persona, quindi anche oggetti di tipo Studente. Infatti, dal momento che esso eredita da Persona, dispone di tutte le proprietà pubbliche della classe base (in altre parole, uno Studente è una Persona, quindi può essere usato in tutti i contesti in cui è richiesta una Persona). Il seguente codice è corretto:

Persona pers = new Persona("Marco", "Rossi");
Studente stud = new Studente("Marco", "Minerva", 232440);
Console.WriteLine(NomiUguali(pers, stud)); // Stampa true

Un fatto molto interessante è che all’interno della routine NomiUguali la variabile stud viene vista come una Persona, e, quindi, di stud sono visibili i metodi e le proprietà pubbliche della classe Persona, non quelli di Studente.

È possibile scaricare un esempio di utilizzo cliccando qui.

L’ereditarietà è singola, in C# come in VB.NET, ovvero una classe può avere solo una classe base, a differenza del C++, che supporta l’ereditarietà multipla: in altre parole, non è possibile definire una classe C che eredita contemporaneamente da A e da B. Torneremo su questi concetti più avanti.

Tutte le lezioni

1 ... 7 8 9 ... 26

Se vuoi aggiornamenti su Ereditarietà inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Ereditarietà

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy