Applicazione delle interfacce in OOP in PHP
Quindi, abbiamo già stabilito che le interfacce sono un buon modo per controllare che tutti i metodi necessari della classe siano implementati.
Consideriamo un altro esempio, più pratico. Supponiamo di avere una classe che memorizzerà un array di oggetti-figura:
<?php
class FiguresCollection
{
private $figures = []; // array per le figure
}
?>
Implementiamo nel nostro classe il metodo addFigure
per aggiungere oggetti alla collezione:
<?php
class FiguresCollection
{
private $figures = [];
// L'oggetto con la figura viene passato come parametro:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
È ovvio che contiamo sul fatto che
al parametro del metodo addFigure venga
passato un oggetto con una figura. Tuttavia non c'è
nessun controllo su questo!
Usiamo un'indicazione di tipo e
indichiamo esplicitamente il tipo degli oggetti come Figure:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Analizziamo cosa abbiamo fatto.
Se Figure fosse una classe realmente esistente,
allora potremmo passare al parametro del metodo oggetti di questa classe, e anche
dei suoi discendenti.
Tuttavia, nel nostro caso Figure è un'interfaccia.
In questo caso, l'indicazione significa che
al parametro del metodo possono essere passati solo
oggetti di classi che implementano la nostra interfaccia.
Proviamo a creare un oggetto della nostra classe e ad aggiungervi delle figure:
<?php
$figuresCollection = new FiguresCollection;
// Aggiungiamo un paio di quadrati:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Aggiungiamo un paio di rettangoli:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
Il tentativo di aggiungere un oggetto di qualsiasi altra classe porterà a un errore:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // qualche altra classe
$figuresCollection->add(new Test); // darà un errore
?>
Cosa ci dà nella pratica questo controllo:
poiché tutte le figure aggiunte alla collezione
implementano l'interfaccia Figure, possiamo
essere sicuri che ognuna di esse avrà il metodo
getSquare e il metodo
getPerimeter.
In futuro, forse, oltre al quadrato e al rettangolo
apparirà, ad esempio, anche un triangolo. In
questo caso anche il triangolo avrà
i metodi getSquare e
getPerimeter.
Nella pratica questo ci dà quanto segue: possiamo
nella classe FiguresCollection creare,
ad esempio, il metodo getTotalSquare, che trova
l'area totale delle figure della collezione. In questo metodo
scorreremo in ciclo l'array delle figure e
per ogni figura chiameremo
il metodo getSquare.
Poiché ogni figura implementa l'interfaccia
Figure, possiamo essere al 100%
sicuri che ogni figura avrà
questo metodo getSquare.
Quindi, ecco l'implementazione del metodo:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Troviamo l'area totale:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // usiamo il metodo getSquare
}
return $sum;
}
}
?>
Senza sbirciare nel mio codice, implementate la stessa
classe FiguresCollection.
Aggiungete alla classe FiguresCollection
il metodo getTotalPerimeter per trovare
il perimetro totale di tutte le figure.