Aplicación de interfaces en POO en PHP
Entonces, ya hemos establecido que las interfaces son una buena manera de controlar que estén implementados todos los métodos necesarios de la clase.
Consideremos otro ejemplo más práctico. Supongamos que tenemos una clase que almacenará un array de objetos-figuras:
<?php
class FiguresCollection
{
private $figures = []; // array para figuras
}
?>
Implementemos en nuestra clase el método addFigure
para agregar objetos a la colección:
<?php
class FiguresCollection
{
private $figures = [];
// Se pasa un objeto con la figura como parámetro:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
Obviamente, contamos con que
el parámetro del método addFigure será
un objeto con una figura. ¡Sin embargo, no hay
ningún control sobre esto!
Usemos una sugerencia de tipos e
indiquemos explícitamente el tipo de objetos como Figure:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Analicemos lo que hemos hecho.
Si Figure fuera una clase realmente existente,
entonces podríamos pasar al parámetro del método objetos de esta clase, así como
también de sus herederos.
Sin embargo, para nosotros Figure es una interfaz.
En este caso, la sugerencia significa que
como parámetro del método solo se pueden pasar
objetos de clases que implementen nuestra interfaz.
Intentemos crear un objeto de nuestra clase y agregarle figuras:
<?php
$figuresCollection = new FiguresCollection;
// Agreguemos un par de cuadrados:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Agreguemos un par de rectángulos:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
El intento de agregar un objeto de cualquier otra clase resultará en un error:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // alguna otra clase
$figuresCollection->add(new Test); // mostrará un error
?>
Qué nos aporta este control en la práctica:
como todas las figuras agregadas a la colección
implementan la interfaz Figure, podemos
estar seguros de que cada una de ellas tendrá el método
getSquare y el método
getPerimeter.
Es posible que en el futuro, además del cuadrado y el rectángulo,
aparezca, por ejemplo, un triángulo. En
ese caso, el triángulo también tendrá
los métodos getSquare y
getPerimeter.
En la práctica, esto nos aporta lo siguiente: podemos
en la clase FiguresCollection hacer,
por ejemplo, el método getTotalSquare, que encuentra
el área total de las figuras de la colección. En este método
recorreremos en ciclo el array de figuras y
a cada figura llamaremos el
método getSquare.
Como cada figura implementa la interfaz
Figure, podemos estar 100%
seguros de que cada figura tendrá
este método getSquare.
Entonces, aquí está la implementación del método:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Encontremos el área total:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // usamos el método getSquare
}
return $sum;
}
}
?>
Sin mirar mi código, implemente la misma
clase FiguresCollection.
Agregue a la clase FiguresCollection
el método getTotalPerimeter para encontrar
el perímetro total de todas las figuras.