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 |
1) http://www.piossascopc.it/images/Abstract-Screen-Computer-1200×1920.jpg