Aplicarea interfețelor în OOP în PHP
Deci, am aflat deja că interfețele sunt o modalitate bună de a controla faptul că toate metodele necesare ale clasei au fost implementate.
Să luăm în considerare un alt exemplu, mai practic. Să presupunem că avem o clasă care va stoca un tablou de obiecte-forme:
<?php
class FiguresCollection
{
private $figures = []; // tablou pentru forme
}
?>
Să implementăm în clasa noastră metoda addFigure
pentru adăugarea de obiecte în colecție:
<?php
class FiguresCollection
{
private $figures = [];
// Ca parametru se transmite un obiect cu forma:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
Evident, contăm pe faptul că
parametrul metodei addFigure va fi
transmis un obiect cu forma. Cu toate acestea, nu există
niciun control pentru asta!
Să folosim indiciul pentru tipuri și
să indicăm explicit tipul obiectelor ca Figure:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Să înțelegem ce am făcut.
Dacă Figure ar fi fost o clasă real existentă,
atunci în parametrul metodei am putea
transmite obiecte ale acestei clase, precum și
ale moștenitorilor săi.
La noi, însă, Figure este o interfață.
În acest caz, indiciul semnifică faptul că
parametrul metodei poate fi transmis doar
obiectelor claselor care implementează interfața noastră.
Să încercăm să creăm un obiect al clasei noastre și să adăugăm în el forme:
<?php
$figuresCollection = new FiguresCollection;
// Să adăugăm câteva pătrate:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Să adăugăm câteva dreptunghiuri:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
Încercarea de a adăuga un obiect al unei alte clase va duce la o eroare:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // o altă clasă
$figuresCollection->add(new Test); // va da eroare
?>
Ce ne oferă în practică un astfel de control:
deoarece toate formele adăugate în colecție,
implementează interfața Figure, putem
fi siguri că fiecare dintre ele va avea metoda
getSquare și metoda
getPerimeter.
Este posibil ca în viitor, pe lângă pătrat și dreptunghi,
să apară, de exemplu, și un triunghi. În
acest caz și triunghiul va avea
metodele getSquare și
getPerimeter.
În practică, acest lucru ne oferă următoarele: putem
în clasa FiguresCollection să facem,
de exemplu, metoda getTotalSquare, care găsește
suprafața totală a formelor colecției. În această metodă
vom parcurge cu un ciclu tabloul de forme și
pentru fiecare formă vom apela
metoda getSquare.
Deoarece fiecare formă implementează interfața
Figure, putem fi 100%
siguri că fiecare formă va avea
această metodă getSquare.
Deci, iată implementarea metodei:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Să găsim suprafața totală:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // folosim metoda getSquare
}
return $sum;
}
}
?>
Fără să vă uitați la codul meu, implementați aceeași
clasă FiguresCollection.
Adăugați în clasa FiguresCollection
metoda getTotalPerimeter pentru a găsi
perimetrul total al tuturor formelor.