Tutorial – Classi in php – Eredità e overriding

Computer connessi

L’eredità tra classi è uno dei fulcri della programmazione a oggetti. Grazie a questa, possiamo usare metodi di una classe superiore (1)

Nell’articolo precedente abbiamo visto una panoramica di cos’è la programmazione a oggetti, della sua strutturale generale in php e del suo uso di base.
In quel tutorial abbiamo parlato di una tecnica chiamata eredità di classe: in breve, è possibile prende i metodi di una classe A e utilizzarli all’interno di una classe B (si dice che B eredita i metodi di A).
“A” è la superclasse (o classe madre) e “B” la sottoclasse (o classe figlia).

L’utilità è intuitiva, ma si comprende fino a fondo solo nella pratica. Se per esempio abbiamo una classe “Persona”, possiamo fare in modo che sia la classe “Studente” che la classe “Lavoratore” prendano i suoi metodi; ma “Studente” e “Lavoratore” non interagiranno in alcun modo tra loro.

Vedremo inoltre che esistono dei sistemi affinché una sottoclasse possa sovrascrivere i metodi di una superclasse, tramite la tecnica che prende il nome di overriding.

Esempio: Studente estende Persona

Riprendiamo l’esempio sopra e vediamo cosa significa effettivamente che la classe “Studente” estende la classe “Persona”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Persona {        
	public function titolo() {
		return "Scheda del soggetto";
	}
}
class Studente extends Persona {      
        public function classe() {
                return "Classe: terza A";
        }

        public function titolo_generale() {
                return $this->titolo();
        }
}

$studente = new Studente;
echo $studente->classe;	// stampa "Classe: terza A"
echo $studente->titolo();	// stampa "Scheda del soggetto"
echo $studente->titolo_generale();	// stampa "Scheda del soggetto"

Come potete vedere, il metodo titolo() appartenente a “Persona” diventa direttamente accessibile dalla classe “Studente”, come se fosse un suo metodo (si noti il richiamo al metodo titolo() all’interno del metodo titolo_generale() ).
Una nota importante: una classe può estendere soltanto un’altra classe. Non potete fargli estendere più di una classe. In compenso possiamo estendere le classi in una cascata concettualmente illimitata; continuando l’esempio sopra, per esempio, nulla vieta di aggiungere la seguente classe:

1
2
3
class TerzaA extends Studente {      
        [...]
}

Public, private, protected

Nel precedente tutorial abbiamo visto tre tipi di attributi assegniabili a proprietà o metodi: public, private e protected.
Nell’eredità si tratta di attributi che fanno la differenza. Prendiamo in considerazione il metodo titolo() della classe “Persona” e vediamo il suo comportamento se gli avessimo assegnato un attributo diverso:


public: il comportamento è quello visto sopra. Il metodo è accessibile sia da “Persona” che da “Studente”.
protected: il metodo è accessibile anche in questo caso da “Persona” e da “Studente”; ma all’esterno della classe non sarebbe stato accessibile. Il seguente richiamo dà errore:

1
2
3
$persona = new Persona;
echo $persona->titolo();	// errore
echo $studente->titolo_generale();	// stampa correttamente "Scheda del soggetto"

private: in questo caso nemmeno “Studente” avrebbe potuto accedere al metodo. Il metodo titolo_generale(), quindi, avrebbe generato un errore perché va a prendersi il metodo titolo(), che essendo private può essere visto solo da “Persona”.

Overriding: sovrascrivere un metodo

Facciamo un passo avanti.
Cosa succede se in una sottoclasse creo un metodo che ha lo stesso nome di un metodo della superclasse? Per esempio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Persona {        
	public function titolo() {
		return "Scheda del soggetto";
	}
}
class Studente extends Persona {      
        public function titolo() {
                return "Scheda dello studente";
        }
}

$persona = new Persona;
$studente = new Studente;
echo $persona->titolo();	// stampa "Scheda del soggetto"
echo $studente->titolo();	// stampa "Scheda dello studente"

Come potete vedere, in questo caso il metodo di “Studente” va a sovrascrivere quello di “Persona”. In pratica, il metodo titolo() di “Studente” ignora il metodo titolo() di “Persona”.
La tecnica prende il nome di overriding.
Se volessimo usare l’istanza $studente per accedere al metodo titolo() di “Persona”, dovremmo affidarci alla clausola parent:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Persona {        
	public function titolo() {
		return "Scheda del soggetto";
	}
}
class Studente extends Persona {      
        public function titolo() {
                return parent::titolo();
        }
}

$studente = new Studente;
echo $studente->titolo();	// stampa "Scheda del soggetto"

Metodi final: impedire l’overriding

Alcune classi implementano delle funzionalità essenziali che non dovrebbe mai essere ridefinte con l’overriding. Pensate, per esempio, a una classe che si occupa esclusivamente di connettersi al database: non avrebbe senso creare una classe che la eredita e che poi vada a sovrascrivere i suoi metodi.
Aggiungendo la keyword final impediamo a un metodo di poter essere ridefinito con l’overriding. Per esempio:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Connessione {        
	final public function select_db() {
		[...]
	}
}
class Prodotti extends Connessione {      
        public function select_db() {
                [...]
        }
}

$prodotti = new Prodotti;
echo $prodotti->select_db();	// dà errore
Copyright immagini

1) http://www.piossascopc.it/images/Abstract-Screen-Computer-1200×1920.jpg

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *