Diciamolo: è capitato un po a tutti di approcciare la OOP (Programmazione ad oggetti) di PHP e bloccarsi di botto nel labirinto logico delle keyword: this, self, static e parent.
In questo mio approfondimento cercherò di spiegarvi in maniera semplice:
- Cosa sono;
- Quando servono;
- Come usarli.
Ma prima di sviscerare Self, Static e Parent occorre menzionare due concetti fondamentali della programmazione ad oggetti:
- Classi
- Ereditarietà
Il $this nelle Classi
Quando si parla di programmazione ad oggetti (OOP) in PHP bisogna fare una premessa teorica ben precisa: un oggetto non è altro che un tipo di dato complesso definito dall’utente (alla stregua degli Array) che segue uno schema ben preciso e già definito, questo schema si chiama Classe.
La classe può essere paragonata ad un progetto di ingegneria edile scritto su carta (con tutti i dovuti calcoli strutturali, elementi e specifiche) che permetterà in un futuro non precisato la realizzazione materiale del progetto, come ad esempio una Palazzina.
La palazzina esiste solo su carta, non ancora fisicamente. Tutti gli elementi disegnati (porte, finestre, muri ecc.. ) sono dei segnaposto da riempire.
Ad esempio, se nel nostro progetto su carta di una Palazzina abbiamo inserito 2 piani, 6 finestre e 2 porte, l’impresa che costruirà l’edificio utilizzerà quello schema per costruirci poi realmente 2 piani, 6 finestre e 2 porte esattamente come nel progetto. Seguendo questo esempio colorato, puoi intuire che il $this è il segnaposto da sostituire con il dato reale.
La keyword $this funzionerà solamente nello scope (area di visibilità) della classe,
class ProgettoEdificio { public $floor; public function __construct($piani, $finestre, $porte) { $this->floor = $piani; }}
Fuori no!
class ProgettoEdificio { public $floor; public function __construct($piani, $finestre, $porte) { $this->floor = $piani; } }-$this->floor = 5;
Dentro la classe utilizzerai il $this, cosi da poter accedere ai metodi e gli attributi della classe. Fuori la classe utilizzerai l’oggetto, cosi da poter accedere ai metodi e gli attributi dell’oggetto istanziato
Dentro la Classe | Fuori la Classe |
---|---|
$this->attributo | $object->attributo |
Facciamo un esempio pratico:
class ProgettoEdificio { public $floor; public $window; public $door; public function __construct($piani, $finestre, $porte) { $this->floor = $piani; $this->window = $finestre; $this->door = $porte; } public function costruisciEdificio() { echo "Costruisco un Edificio con $this->floor, $this->window e la bellezza di $this->door."; }} $palazzina1 = new ProgettoEdificio(2, 6,2);$palazzina1->costruisciEdificio(); // Qui non posso usare il $this, ho l'oggetto $palazzina1!
Ereditarietà
L’ereditarietà in PHP, come in altri linguaggi di programmazione, è un concetto di astrazione che permette di definire delle classi Figlio partendo da classi Genitore gia esistenti.
Questa gerarchia permette di riutilizzare il codice esistente e di evitare di doverlo riscrivere, in quanto le nuove classi erediteranno Attributi e Metodi della classe genitore.
In questo modo, ogni classe figlio può utilizzare tutti i metodi e le proprietà della classe genitore ( Nonno, bisnonno ecc..), ma ovviamente potrà specializzare altri attributi e metodi propri.
Un po come un “figlio di papà” che eredita i soldi e l’azienda del papi ma decide poi di sperperare tutto e aprire un centro scommesse sotto casa.
class GenitoreRicco { public $soldi;} class Figlio extends GenitoreRicco { public function spendiTuttoEApricentroScommesse(){ return $this->soldi = 0; }} $antonio = new Figlio(); // Il figlio erediterà tutti i soldi del genitore$antonio->spendiTuttoEApricentroScommesse();//Il figlio ha appena speso tutto
Che cosa sono self, static e parent?
Appurato che: il $this è il segnaposto di un dato futuro, che verrà poi trasformato in un oggetto nel momento dell’istanza di quest’ultimo.
Bene, è giunto il momento di introdurre il concetto di Static.
Static
In PHP solitamente gli oggetti vengono definiti come dinamici, ovvero vengono istanziati al momento e si valorizzano con i dati di input.
Diametralmente opposta, invece, è la parola“static“.
Static è una keyword che viene utilizzata per definire proprietà o metodi statici che sono condivisi da TUTTE le istanze della classa in oggetto e dei relativi figli.
Solitamente hanno un valore di default.
Non contemplano dati inseriti dinamicamente dall’esterno.
Un attributo o un metodo statico sono definiti nella classe stessa in maniera statica e non in un secondo momento da un’istanza specifica della classe.
class Counter { public static $count = 0; public static $results = 0; public static function test() { echo "Funziona statica di test"; }}
Questo significa che, non avendo bisogno di input inseriti dinamicamente, si possono richiamare senza creare un’istanza della classe (non ci serve creare un ipotetico oggetto $contatore):
class Counter { public static $count = 0; public static function add() { self::$count++; } public static function sub() { self::$count--; } public static function test() { echo "Funziona statica di test"; }} Counter::add();Counter::sub();Counter::add();Counter::test(); echo Counter::$count; //1
Self
Abbiamo appena analizzato Static, passiamo a Self.
La keyword self indicherà sempre e comunque la classe che lo richiama e potrai richiamarla all’interno di un metodo statico o di un metodo di una classe. Utilizzando il concetto del Sottinteso.
Uhm, in che senso?
Nel senso che se richiamerai self dentro Classe1, self sarà appunto Classe1.
Se invece richiamerai self dentro Classe45, self sarà appunto Classe45.
Immaginalo come un pronome utilizzato all’interno di una lettera di felicitazioni di un matrimonio. Senza il concetto del Sottinteso avrai:
Antonio,hai trovato un amore speciale da tutelare, condividere e proteggere.Vivi felice e contento con Giovanna. ----- Buona vita insieme Antonio e Giovanna!
Utilizzando il concetto Sottinteso (self) avrai la chiusura in questo modo:
Antonio,hai trovato un amore speciale da tutelare, condividere e proteggere.Vivi felice e contento con Giovanna. ----- Buona vita insieme!
In questo caso abbiamo rimosso completamente i nomi in quanto è Sottinteso che sia riferito a loro.
Il self ti servirà quando proverai ad accedere ad attributi o metodi statici definiti nella classe.
Ti accorgerai che richiamare un metodo statico in questo modo:
class Articolo { public static $title = "Testo Standard"; public function metodo() { return $this->title;//No }} $nuovo = new Articolo();echo $nuovo->metodo();
Ti ritornerà un errore Notice: Accessing static property Articolo::$title as non static
Il self ti permetterà di richiamare la classe stessa senza ripercussioni:
class Articolo { public static $title = "Testo Standard"; public function metodo() { return self::$title; }} $nuovo = new Articolo();echo $nuovo->metodo();
Riprendendo l’esempio di poco fa:
class Counter { public static $count = 0; public static $results = 0; public static function test() { echo "Funziona statica di test"; }}
Puoi vedere come utilizzare il self all’interno della classe per richiamare attributi e metodi:
class Counter { public static $count = 0; public static function add() { self::$count++; } public static function sub() { self::$count--; } public static function test() { echo "Funziona statica di test"; }}
E fuori invece?
Counter::add();Counter::sub();Counter::add();Counter::test(); echo Counter::$count; //1
Dentro la classe utilizzerai il self::, cosi da poter accedere accedere ai metodi e gli attributi della classe.
Fuori la classe utilizzerai il nome stesso della Classe, cosi da poter accedere accedere ai metodi e gli attributi dell’oggetto istanziato.
Dentro la Classe | Fuori la Classe |
---|---|
self::$attributo | Classe::$attributo |
self::myFunction() | Classe::myFunction() |
Parent
La Keyword Parent rappresenta la classe genitore della classe corrente.
Può essere utilizzata per accedere ai membri e ai metodi della classe genitore.
L’utilizzo di Parent è particolarmente utile quando si desidera sovrascrivere un metodo nella classe figlia, ma si desidera anche accedere al metodo originale della classe genitore. In questo caso, è possibile utilizzare “parent” per accedere al metodo della classe genitore originale.
Noi ad esempio, vogliamo sovrascrivere il costruttore, ma comunque preservare il costruttore del genitore.
Ecco un esempio:
class ProgettoEdificio { public $floor; public function __construct($piani) { $this->floor = $piani; }} class Casa extends ProgettoEdificio { public $window; public function __construct($piani,$finestre) { parent::__construct($piani); $this->window = $finestre; }}