Интерфейсы в PHP: контракты для классов

Интерфейсы в PHP

Сегодня мы поговорим об интерфейсах в PHP. Прежде чем начать разговор непосредственно об интерфейсах, давайте сначала я расскажу вам о том, какую проблему они решают и почему в них появилась необходимость.

Интерфейсы в PHP мы будем изучать на примере геометрических фигур. Пусть у нас есть прямоугольник, квадрат и круг, и, например, мы хотим вычислить их площади. Мы прекрасно помним, что для вычисления площади прямоугольника нам нужно знать длины двух соседних сторон, для квадрата – длину одной стороны, для круга – его радиус. Давайте создадим классы, которые будут описывать свойства этих фигур, а также создадим у методы, для вычисления их площади.

Прямоугольник.

Код доступен только после покупки курса ООП в PHP.

Квадрат.

Код доступен только после покупки курса ООП в PHP.

Круг.

Код доступен только после покупки курса ООП в PHP.

Константы класса

Число Пи мы здесь задали в переменную, однако для таких вот постоянных вещей, которые в процессе работы программы не изменяются, лучше использовать константы. Они определяются с помощью слова const. Вот так:

Код доступен только после покупки курса ООП в PHP.

Константы принято задавать в самом начале класса и называть их CAPS-ом с подчеркушками. Вот примеры того, как могут называться константы: DB_NAME, COUNT_OF_OBJECTS.

Для того, чтобы обратиться к константе, нужно использовать конструкцию self::ИМЯ_КОНСТАНТЫ, или ИмяКласса::ИМЯ_КОНСТАНТЫ. Ключевое слово self – это обращение к текущему классу (как $this – обращение к текущему объекту, не путайте эти понятия). Константы принадлежат классу, а не его объектам.

Давайте вынесем число Пи в константу.

Код доступен только после покупки курса ООП в PHP.

Теперь мы можем использовать её и в других методах. Или даже в других классах, обратившись к ней через Circle::PI.

Интерфейсы

Окей, разобрались с константами и имеем в итоге 3 объекта, описывающих геометрические фигуры и реализацию для вычисления их площадей. Если присмотреться, то мы видим, что во всех классах определён метод calculateSquare(), возвращающий float. Можно сказать, что у них есть что-то общее.

Допустим, мы хотели бы, чтобы у нас были фигуры, которые умеют считать свою площадь. То есть, говоря чуть более абстрактно, какие-то наши классы обязаны реализовать какой-то внешний интерфейс, а именно – иметь метод calculateSquare(), который всегда возвращает float.
Для этой задачи в PHP есть интерфейсы. Это такие «контракты», которые класс должен соблюдать, если он на это «подписался». А говоря языком программистов, классы могут реализовывать интерфейсы.

Интерфейс – это описание public методов, которые представляют собой только название метода, описание их аргументов и возвращаемый тип. Тело метода в интерфейсе не описывается.
Давайте создадим интерфейс для нашего случая.

Код доступен только после покупки курса ООП в PHP.

Чтобы обязать класс реализовать этот интерфейс нужно использовать слово implements после имени класса.

Код доступен только после покупки курса ООП в PHP.

Один класс может реализовывать сразу несколько интерфейсов, в таком случае они просто перечисляются через запятую.

Код доступен только после покупки курса ООП в PHP.

IDE PhpStorm автоматически понимает, что наш класс реализует интерфейс и рисует слева от методов специальные иконки. Если по ним кликнуть, то нас перекинет на интерфейс.
Подсветка интерфейсов в PhpStorm

Ну и в интерфейсе если кликнуть на такую иконку, то нам откроется список мест, где этот интерфейс реализован.
Реализации интерфейса

Если же мы напишем, что класс реализует какой-то интерфейс, но не реализуем его, то получим ошибку. Об этом нам даже подскажет IDE. Давайте удалим метод calculateSquare() из класса Circle. IDE любезно подчеркнёт красным строку, в которой мы говорим, что класс реализует интерфейс.
Напоминание о необходимости реализации интерфейса

Если же мы попробуем запустить этот код, то и вовсе словим фатальную ошибку.
Ошибка при нереализованном интерфейсе

Так что давайте этот метод вернём обратно =)

Что ещё стоит сказать об интерфейсах – один интерфейс может содержать требования по реализации нескольких методов. Они просто перечисляются один за другим, вот так:
interface CalculateSquare

Код доступен только после покупки курса ООП в PHP.

Но мы пока ограничимся одним методом calculateSquare().

Окей, так для чего это всё?

В программировании зачастую требуется проверить, что перед нами сейчас какой-то конкретный тип объектов, то есть что перед нами экземпляр какого-то класса, либо что этот объект реализует какой-то интерфейс. Для этого используется конструкция instanceof. С её помощью можно понять, является ли объект экземпляром какого-то класса, или реализует интерфейс. Эта конструкция возвращает true или false.

Код доступен только после покупки курса ООП в PHP.

Результат:

Код доступен только после покупки курса ООП в PHP.

Всё верно, объект $circle1 является экземпляром класса Circle. Давайте теперь проверим, является ли он экземпляром класса Rectangle.

Код доступен только после покупки курса ООП в PHP.

Результат:

Код доступен только после покупки курса ООП в PHP.

И снова всё верно, он не является экземпляром класса Rectangle.

А теперь давайте проверим, является ли он объектом, класс которого реализует интерфейс CalculateSquare.

Код доступен только после покупки курса ООП в PHP.

И мы получим:

Код доступен только после покупки курса ООП в PHP.

Вуаля! Теперь мы перед тем как попросить какой-либо объект посчитать свою площадь, можем проверить, есть ли у него такой метод, то есть, реализует ли он соответствующий интерфейс.
Давайте добавим во все наши классы информацию о том, что они реализуют интерфейс CalculateSquare.

Код доступен только после покупки курса ООП в PHP.

Давайте теперь насоздаём объектов этих классов и положим их в массив:

Код доступен только после покупки курса ООП в PHP.

Теперь мы можем в цикле пройтись по ним, и для тех, которые реализуют интерфейс, посчитать площадь.

Код доступен только после покупки курса ООП в PHP.

Результат:

Код доступен только после покупки курса ООП в PHP.

Давайте теперь уберём из класса Rectangle упоминание о том, что он реализует этот интерфейс.
class Rectangle

Код доступен только после покупки курса ООП в PHP.

И снова попробуем запустить код.

Код доступен только после покупки курса ООП в PHP.

Как видим, проверка успешно отработала и объект класса Rectangle был пропущен.

Полный код, полученный в ходе урока:

Код доступен только после покупки курса ООП в PHP.

На этом с интерфейсами пока всё. В домашке будет ещё одна интересная функция, которая позволит вам узнать об объектах ещё кое-что.