Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 37 di 50
  • livello avanzato
Indice lezioni

Superclassi, sottoclassi e overriding

Analizziamo le relazioni che intercorrono fra superclassi e sottoclassi
Analizziamo le relazioni che intercorrono fra superclassi e sottoclassi
Link copiato negli appunti

Dopo avere imparato come estendere le classi, come creare gerarchie composte e come utilizzare tutti i possibili indicatori di visibilità, è arrivato il momento di analizzare con maggiore dettaglio le relazioni che intercorrono tra superclassi e sottoclassi.

Come abbiamo già dichiarato in precedenza, le superclassi (anche definite classi "parent", genitori o antenate) sono le classi che vengono estese e che offrono le loro funzionalità, mentre le sottoclassi sono l'esatto opposto, ovvero quelle classi che estendono le superclassi ereditandone le funzionalità.

Abbiamo inoltre imparato che i metodi pubblici e protetti vengono ereditati dalle sottoclassi, ma non abbiamo ancora visto cosa accade quando si dichiarano elementi con lo stesso namespace all'interno delle sottoclassi (ridefinizione o overriding).

Senza attuare delle particolari strategie, la proprietà o il metodo originale viene sovrascritto da quello nuovo:

class A {
        public function sayHello() {
                echo "Hello!";
        }
}
class B extends A {
        public function sayHello() {
                echo "Ciao Ciao!";
        }
}
$b = new B();
// stampa "Ciao Ciao!"
$b->sayHello();

Ciò significa che con le conoscenze attuali, nello snippet precedente non abbiamo alcun modo di accedere al metodo sayHello della classe A attraverso le istanze della classe B.

Questa funzionalità diventa attuabile tramite la keyword parent, che unita all'operatore di risoluzione dell'ambito ("::") ed al nome dell'elemento desiderato, permette di richiamare gli elementi della classe genitore direttamente nelle sottoclassi:

class A {
        public function sayHello() {
                echo "Hello!";
        }
}
class B extends A {
        public function sayHello() {
                parent::sayHello();
                echo "Ciao Ciao!";
        }
}
$b = new B();
// stampa "Hello! Ciao Ciao!"
$b->sayHello();

In questo modo, abbiamo potuto richiamare il metodo sayHello della classe A direttamente nel metodo ridefinito presente nella classe B. Grazie all'uso della parola chiave parent, è possibile dunque condividere informazioni tra le classi senza l'occorrenza di riscrivere completamente un metodo nel caso in cui questo venga ridefinito.

Nel seguente esempio si può notare come, richiamando il metodo costruttore della classe parente sia possibile recuperare la fase di setting dei valori senza ripeterla inutilmente, ma aggiungendo solo le funzionalità veramente nuove:

class A {
        public function __construct($a, $b, $c, $d) {
                $this->a = $a;
                $this->b = $b;
                $this->c = $c;
                $this->d = $d;
        }
        // metodi...
}
class B extends A {
        public function __construct($a, $b, $c, $d, $e) {
                parent::__construct($a, $b, $c, $d);
                $this->e = $e;
        }
        // metodi...
}
$b = new B(10, 20, 30, 40, 50);
echo $b->a;  // stampa 10
echo $b->b;  // stampa 20
echo $b->c;  // stampa 30
echo $b->d;  // stampa 40
echo $b->e;  // stampa 50

Ovviamente la keyword parent, oltre che con i metodi non statici, può essere usata in collaborazione con le costanti, con le proprietà statiche e con i metodi statici:

class A {
        const A = 10;
        public static $a = 10;
        public function sayHello() {
                echo "Hello!";
        }
        public static function sayHelloAgain() {
                echo "Hello again!";
        }
}
class B extends A {
        public $b = 20;
        public function sayHello() {
                echo parent::A;
                echo parent::$a;
                parent::sayHelloAgain();
        }
}
$b = new B();
// stampa "10 10 Hello again!"
$b->sayHello();

Conclusione

I concetti di superclasse,sottoclasse e ridefinizione presentati in questa lezione costituiscono il vero significato della programmazione orientata agli oggetti. Tutta la potenza, la flessibilità e la mantenibilità delle gerarchie OOP infatti, ruotano attorno a questi presupposti, che permettono di creare codice veramente modulare e soprattutto robusto.

Il concetto di ridefinizione (o overriding) attuabile tramite la keyword parent in particolare, permette di elevare il codice a livelli completamente nuovi rispetto al modello procedurale.

Tuttavia è addirittura possibile che accadano particolari situazioni in cui non si vuole attuare l'overriding: ciò è possibile in PHP tramite l'uso di una particolare keyword che analizzeremo dettagliatamente nella prossima lezione: quest'ultima prende il nome di final.

Ti consigliamo anche