Aplicação de Interfaces em POO em PHP
Então, já estabelecemos que interfaces são uma boa maneira de controlar que todos os métodos necessários de uma classe estejam implementados.
Vamos considerar outro exemplo, mais prático. Suponha que temos uma classe que irá armazenar um array de objetos de figuras:
<?php
class FiguresCollection
{
private $figures = []; // array para figuras
}
?>
Vamos implementar em nossa classe o método addFigure
para adicionar objetos à coleção:
<?php
class FiguresCollection
{
private $figures = [];
// Um objeto de figura é passado como parâmetro:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
Obviamente, estamos contando com o fato de que
o parâmetro do método addFigure será
um objeto de figura. No entanto, não há
nenhum controle sobre isso!
Vamos usar uma dica de tipo e
explicitamente especificar o tipo dos objetos como Figure:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Vamos entender o que fizemos.
Se Figure fosse uma classe realmente existente,
poderíamos passar objetos dessa classe, bem como
seus herdeiros, como parâmetro do método.
No nosso caso, no entanto, Figure é uma interface.
Neste caso, a dica de tipo significa que
apenas objetos de classes que implementam nossa interface podem ser passados como parâmetro do método.
Vamos tentar criar um objeto da nossa classe e adicionar algumas figuras a ele:
<?php
$figuresCollection = new FiguresCollection;
// Vamos adicionar alguns quadrados:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Vamos adicionar alguns retângulos:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
Tentar adicionar um objeto de qualquer outra classe resultará em um erro:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // alguma outra classe
$figuresCollection->add(new Test); // resultará em erro
?>
O que esse controle nos dá na prática:
como todas as figuras adicionadas à coleção
implementam a interface Figure, podemos
ter certeza de que cada uma delas terá o método
getSquare e o método
getPerimeter.
É possível que no futuro, além do quadrado e do retângulo,
surja, por exemplo, um triângulo. Neste
caso, o triângulo também terá
os métodos getSquare e
getPerimeter.
Na prática, isso nos dá o seguinte: podemos
na classe FiguresCollection fazer,
por exemplo, o método getTotalSquare, que encontra
a área total das figuras da coleção. Neste método,
vamos percorrer o array de figuras com um loop e
para cada figura chamar o
método getSquare.
Como cada figura implementa a interface
Figure, podemos estar 100%
seguros de que cada figura terá
este método getSquare.
Então, aqui está a implementação do método:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Vamos encontrar a área total:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // usamos o método getSquare
}
return $sum;
}
}
?>
Sem espiar o meu código, implemente uma
classe FiguresCollection igual.
Adicione à classe FiguresCollection
o método getTotalPerimeter para encontrar
o perímetro total de todas as figuras.