Per offrirti un'esperienza di navigazione sempre migliore, questo sito utilizza cookie propri e di terze parti, partner selezionati. I cookie di terze parti potranno anche essere di profilazione.
Le tue preferenze si applicheranno solo a questo sito web. Puoi modificare le tue preferenze in qualsiasi momento ritornando su questo sito o consultando la nostra informativa sulla riservatezza.
E' possibile rivedere la nostra privacy policy cliccando qui e la nostra cookie policy cliccando qui.
Per modificare le impostazioni dei cookies clicca qui
  • seguici su feed rss
  • seguici su twitter
  • seguici su linkedin
  • seguici su facebook
  • cerca

SEI GIA' REGISTRATO? EFFETTUA ADESSO IL LOGIN.



ricordami per 365 giorni

HAI DIMENTICATO LA PASSWORD? CLICCA QUI

NON SEI ANCORA REGISTRATO ? CLICCA QUI E REGISTRATI !

Come estendere una classe in PHP ed il concetto di ereditarietà.

di :: 18 novembre 2022
Come estendere una classe in PHP ed il concetto di ereditarietà.

In un articolo precedente ci siamo già occupati  di come estendere una classe e quindi della visibilità delle proprietà e metodi di una classe (public, private e protected), premessa fondamentale di questo argomento.

Con questo nuovo articolo ho voluto integrare questo argomento con nuovi esempi per spiegare ancora meglio come estendere una classe tenendo conto dei vincoli legati alla visibilità delle proprietà e dei metodi.

Partiamo da questo:

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;
}

class ChildClass extends ParentClass{

}

$obj = new ChildClass();
echo $obj->proprieta1;
?>

Estendere una classe significa acquisire metodi e proprietà di un'altra classe padre, estendone le funzionalità.

Nel nostro esempio, inizializziamo la classe ChildClass, e lo script renderà il numero 1: questo perchè la classe child non sta ancora implementando nulla.

Mentre nell'esempio successivo, la ChildClass sovrascive (facciamo un OVERRIDE) il valore della proprietà $proprieta1, definita nella classe padre, per cui lo script renderà il numero 16

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
}

$obj = new ChildClass();
echo $obj->proprieta1;
?>

Nel nostro esempio abbiamo sovrascritto una proprietà di tipo public.

Ordine di visibilità di proprietà e metodi

Una classe child può accedere (e modificare) le proprietà della classe parent che hanno visibilità di tipo public e di tipo protected, ma NON alle proprietà con visibilità private.

Inoltre nella classe child la proprietà dovrà avere visibità superiore o uguale a quella della classe parent, per cui $proprieta1 nella child non potrà essere protected.

Ricordiamo che l'ordine di visibilità, dal maggiore al minore, è PUBLIC, PROTECTED, PRIVATE.

Vediamo un altro esempio in cui la classe parent ha un metodo "getProperty3" che rende il valore della proprietà "$proprietà3"

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3() {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Lo script restituirà il numero 3. Adesso facciamo un override della proprietà "$proprieta3", che ha visibilità protected e per questo possiamo farlo.

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3() {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Il risultato dello script è il numero 24: la classe child ha infatti sovrascritto il valore di $proprieta3 per cui il metodo parent getProperty3 renderà quel valore.

Quindi, ricapitolando, se hai una proprietà con visibilità public o protected, puoi sovrascriverne il valore dalla classe child, mentre non puoi fare un override della proprietà $proprieta2 perchè questa proprietà è di tipo private.

Procediamo con un'altro esempio, in cui la classe child contiene lo stesso metodo getProperty3 presente nella classe parent.

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3() {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;

   public function getProperty3() {
     return parent::getProperty3();
   }
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Dopo aver instanziato l'oggetto, quando chiamiamo getProperty3 contenuto nella classe child, che a sua volta richiama l'analogo metodo getProperty3 presente nella classe parent: non viene quindi aggiunta alcuna funzionalità alla classe parent. Il risultato sarà sempre 24.

Vediamo adesso di estenderne le funzionalità: facciamo in modo che la getProperty3 risponda con una frase

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3() {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;

   public function getProperty3() {
     $result = parent::getProperty3();
     return "il risultato è ".$result;
   }
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Lo script adesso renderà "il risultato è 24": abbiamo così esteso il metodo getProperty3.

Così come per le proprietà, una classe child può accedere (e modificare) i metodi della classe parent che hanno visibilità di tipo public e di tipo protected, ma NON ai metodi con visibilità private. E non è neanche possibile nella classe child utilizzare una visibilità inferiore. Per cui nella child il medoto getProperty3 non potrà essere protected: otterremo un errore.

Type hinting di metodi e proprietà

Se utilizziamo il type hinting, occorrerà estendere un metodo o proprietà usando lo stesso type hinting.

Ad esempio questo script renderebbe errore

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3(): string {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;

   public function getProperty3() {
     $result = parent::getProperty3();
     return "il risultato è ".$result;
   }
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Lo script, per essere corretto, devi indicare "string" come type hinting per entrambi i metodi

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3(): string {
     return $this->proprieta3;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;

   public function getProperty3(): string {
     $result = parent::getProperty3();
     return "il risultato è ".$result;
   }
}

$obj = new ChildClass();
echo $obj->getProperty3();
?>

Lo stesso vale anche per gli argomenti dei metodi. Ad esempio se nella classe parent abbiamo un metodo "printText" con un argomento con type hinting "string", per estendere questo metodo nella classe child, devo obbligatoriamente accettare un argomento di tipo "string".

<?php
class ParentClass{
   public $proprieta1 = 1;
   private $proprieta2 = 2;
   protected $proprieta3 = 3;

   public function getProperty3(): string {
     return $this->proprieta3;
   }

   public function printText(string $text) {
     echo $text;
   }
}

class ChildClass extends ParentClass{
   public $proprieta1 = 16;
   protected $proprieta3 = 24;

   public function getProperty3(): string {
     $result = parent::getProperty3();
     return "il risultato è ".$result;
   }

   public function printText(string $text) {
     echo "ciao da ".$text;
   }
}

$obj = new ChildClass();
echo $obj->printText("Giulio");
?>

Quindi ricapitolando, il metodo dichiarato in una classe child (il numero di argomenti, il tipo di argomenti, ...) deve essere dichiarato nello stesso modo con cui è dichiato nella classe parent.

Come sovrascrivere una costante

Anche le costanti, di cui ci siamo già occupati in un articolo precedente, possono essere sovrascritte.

Ad esempio, se abbiamo una costante nella classe parent, possiamo ridichiarla senza problemi nella classe child

<?php
class ParentClass{
   const MIA_COSTANTE = '3';
}

class ChildClass extends ParentClass{
   const MIA_COSTANTE = '6';
}

$obj = new ChildClass();
echo ChildClass::MIA_COSTANTE;
?>

Facciamo attenzione al livello di visibilità della costante.

Se ad esempio nel parent la costante ha visibilità private, nella child potrà essere solo public, perchè protected è un livello inferiore rispetto a private.

In questo esempio, lo script è corretto perchè la funzione getConstant della classe child fa rifrimento alla costante presente nel parent che ha visibilità protected

<?php
class ParentClass{
   protected const MIA_COSTANTE = '3';
}

class ChildClass extends ParentClass{

    public function getConstant(){
       return self::MIA_COSTANTE;
    }
}

$obj = new ChildClass();
echo $obj->getConstant();
?>

Questo script invece produce un errore, perchè la costante nel parent ha visibilità private per cui non è accessibile dal child

<?php
class ParentClass{
   private const MIA_COSTANTE = '3';
}

class ChildClass extends ParentClass{

    public function getConstant(){
       return self::MIA_COSTANTE;
    }
}

$obj = new ChildClass();
echo $obj->getConstant();
?>

Come impedire di estendere un classe: final class

Se non vogliamo che un classe possa essere estesa dobbiamo precederne il nome con la chiave final.

Questo esempio renderà un errore perchè stiamo cercando di estendere la classe ParentClass che è dichiarata come "final" per cui non estendibile.

<?php
final class ParentClass{
   private const MIA_COSTANTE = '3';
}

class ChildClass extends ParentClass{

    public function getConstant(){
       return self::MIA_COSTANTE;
    }
}

$obj = new ChildClass();
echo $obj->getConstant();
?>

Questo final si può applicare anche ai metodi, come in questo esempio che produrrà un errore perchè abbiamo dichiarato il metodo hello del parent come final, ed abbiamo tentanto di estenderlo dalla classe child.

<?php
class ParentClass{

   final public function hello() {
     echo "ciao da Giulio";
   }
}

class ChildClass extends ParentClass{

   final public function hello() {
     echo "ciao da Elisa";
   }
}

$obj = new ChildClass();
echo $obj->hello();
?>

Potrebbe interessarti

 
 
 
 
pay per script

Hai bisogno di uno script PHP personalizzato, di una particolare configurazione su Linux, di una gestione dei tuoi server Linux, o di una consulenza per il tuo progetto?

x

ATTENZIONE