Применение интерфейсов в ООП на PHP
Итак, мы уже выяснили, что интерфейсы хороший способ контролировать то, что реализованы все необходимые методы класса.
Давайте рассмотрим еще один, более практический, пример. Пусть у нас есть класс, который будет хранить в себе массив объектов-фигур:
<?php
class FiguresCollection
{
private $figures = []; // массив для фигур
}
?>
Реализуем в нашем классе метод addFigure
для добавления объектов в коллекцию:
<?php
class FiguresCollection
{
private $figures = [];
// Параметром передается объект с фигурой:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
Очевидно, что мы рассчитываем на то, что
параметром метода addFigure
будет
передаваться объект с фигурой. Однако за
этим нет никакого контроля!
Давайте используем подсказку для типов и
явно укажем тип объектов как Figure
:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Давайте разберемся с тем, что мы сделали.
Если бы Figure
был реально существующим
классом то в параметр метода мы смогли бы
передать объекты этого класса, а также и
его наследников.
У нас, однако, Figure
- это интерфейс.
В таком случае подсказка обозначает то, что
параметром метода могут быть переданы только
объекты класса, реализующих наш интерфейс.
Давайте попробуем создать объект нашего класса и добавить в него фигуры:
<?php
$figuresCollection = new FiguresCollection;
// Добавим парочку квадратов:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Добавим парочку прямоугольников:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
Попытка добавить объект какого-либо другого класса приведет к ошибке:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // какой-то другой класс
$figuresCollection->add(new Test); // выдаст ошибку
?>
Что на практике дает нам такой контроль:
так как все фигуры, добавленные в коллекцию,
реализуют интерфейс Figure
, мы можем
быть уверены, что у каждой из них будет метод
getSquare
и метод getPerimeter
.
Возможно в дальнейшем кроме квадрата и прямоугольника
появится, например, еще и треугольник. В
этом случае и у треугольника также будут
методы getSquare
и getPerimeter
.
На практике это дает нам следующее: мы можем
в классе FiguresCollection
сделать,
к примеру, метод getTotalSquare
, находящий
полную площадь фигур коллекции. В этом методе
мы будем перебирать циклом массив фигур и
у каждой фигуры вызывать метод getSquare
.
Так как каждая фигура реализует интерфейс
Figure
, мы можем быть на 100%
уверены в том, что у каждой фигуры будет
этот метод getSquare
.
Итак, вот реализация метода:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Найдем полную площадь:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // используем метод getSquare
}
return $sum;
}
}
?>
Не подсматривая в мой код реализуйте такой
же класс FiguresCollection
.
Добавьте в класс FiguresCollection
метод getTotalPerimeter
для нахождения
суммарного периметра всех фигур.