Le classi astratte e i metodi astratti, in PHP
Dopo aver introdotto le classi in PHP, aver visto cos'è la visibilità e come estendere una classe, oggi ci occupiamo delle classi astratte.
Le classi astratte sono un altro importante aspetto della programmazione ad oggetti.
Una classe astratta è un particolare tipo di classe che non può essere istanziata, cioè non è possibile creare un oggetto da una classe astratta, ma può solo essere estesa da un’altra classe.
Possiamo considerare questa tipologia di classe come una "base di partenza" o un "modello" per la creazione di classi figlie.
Inoltre all'interno di una classe astratta è possibile definire uno o più metodi astratti. La differenza tra un metodo normale e un metodo astratto è che il metodo astratto non viene "implementato" cioè non si inserisce nessun codice all’interno del metodo, a da questo deriva la definizione di "metodo senza corpo". Questo metodo astratto però dovrà essere implementato dalla classe figlia, con lo stesso nome e stessi eventuali argomenti.
All'interno della classe astratta ci possono essere anche metodi non astratti, oltre a quello astratto.
Ecco le regole da tenere a mente quando si vuole estendere una classe partendo da una classe parent astratta:
- devi dichiarare gli stessi metodi astratti dichiarati nella classe parent
- gli argomenti dei metodi devono essere gli stessi dei metodi astratti del parent
- i metodi della classe child possono avere argomenti aggiuntivi rispetto a quelli presenti nei metodi astratti del parent
- se la classe astratta parent utilizza un type hinting, o lo utilizza negli argomenti, la classe child deve rispettare lo stesso type hinting
- la visibilità dei metodi child deve essere superiore o ugule a quella del parent
- non si possono creare oggetti dalla classe astratta
Capiamo questi concetti con un esempio.
Abbiamo una classe astratta "L" che contiene un metodo pubblico normale "getName", ed un metodo astratto "schedaUser" che, come vediamo, non ha codice al suo interno.
Proviamo ad istanziare questa classe astratta.
<?php
abstract class L {
public abstract function schedaUser(int $idUser);
public function getName()
{
echo "giulio";
}
}
$obj=new L;
?>
La classe astratta "L" non puo essere istanziata e l'errore visualizzato sarà il seguente
Fatal error: Uncaught Error: Cannot instantiate abstract class L in /var/www/hml/test/index.php:12
All'interno della classe astratta, come sappiamo, possiamo implementare dei metodi che sono ereditati dalle classi figlie, e che possono o meno essere utilizzati dalle classi figlie, come la "getName".
Ma se creiamo un metodo astratto, questo dovrà essere per forza utilizzato dalla classe figlia, come nel nostro esempio il metodo "schedaUser".
Estendiamo l'esemio percedente ed aggiungiamo la classe figlia "M" che estende la classe "L": all'interno della classe figlia devo utilizzare il metodo "schedaUser".
Istanzio quindi un oggetto di classe "M" ed accedo al metodo "schedaUser".
<?php
abstract class L {
public abstract function schedaUser($idUser);
public function getName()
{
echo "giulio";
}
}
class M extends L {
public function schedaUser($idUser)
{
echo "elisa";
}
}
$obj=new M;
M->schedaUser(12);
?>
Lanciamo lo script ed il risultato sarà "elisa".
Attenzione: la visilità del metodo "schedaUser" della classe CHILD deve essere maggiore o uguale alla visibilità del metodo astratto della classe PARENT, per cui, nel nostro esempio, non possiamo impostare, nel metodo "schedaUser" della classe CHILD, una visibilità protected o private, perchè sono visibilità inferiori rispetto a public.
Vediamo un ultimo esempio completo che vi lascio da studiare.
<?php
abstract class Shape{
public $color;
abstract public function getArea(): float;
public function __construct($color){
$this->color = $color;
}
public function getColor(){
return $this->color;
}
}
class Circle extends Shape{
public $radius;
public function __construct($color,$radius){
parent::__construct($color);
$this->radius= $radius;
}
public function getArea(): float{
return $this->radius * $this->radius * 3.14;
}
}
class Rectangle extends Shape{
public $width;
public $length;
public function __construct($color,$width,$length){
parent::__construct($color);
$this->width = $width;
$this->length = $length;
}
public function getArea(): float{
return $this->width * $this->length;
}
}
$t = new Rectangle("green", 10, 5);
echo $t->getArea();
$t = new Circle("red", 5);
echo $t->getArea();
?>
Le classi "Circle" e "Rectangle" devono obbligatoriamente avere il metodo "getArea" della classe astratta con almeno il primo argomento "color" previsto nella classe astratta.
Il primo echo renderà il numero 50, il secondo 78.5
Potrebbe interessarti
- Le interfacce in PHP
- Le costanti di una classe in PHP
- Come estendere una classe in PHP ed il concetto di ereditarietà.
- Le proprietà e i metodi STATICI in PHP
- Il metodo costruttore in PHP
- Autoloading classi in PHP, con un occhio ai namespace ed allo standard di programmazione psr-4.
- Cos'è il type hinting, la sua evoluzione nelle varie versioni di PHP, ed il controllo sulla tipologia di dato con la modalità strict_mode.
- I metodi magici in PHP.
- Cosa sono i namespace in PHP. La guida completa, con esempi.
- Cosa sono i trait in PHP. La guida completa con esempi.
- Le classi in PHP. introduzione alla programmazione in stile OOP, metodi e proprietà di una classe.