обработка данных

Нажмите сюда, если долго загружается,
либо "ESC" - отмена
 
Заказ обратного звонка
Заказать звонок
Наш специалист свяжется с Вами и ответит на все вопросы
Обработка данных
Наш специалист свяжется с Вами и ответит на все вопросы.
OK

Готовимся к собеседованию по PHP: об интерфейсах и совместимости сигнатур

Источник: https://habrahabr.ru
Время чтения: ~6 мин
Готовимся к собеседованию по PHP:  об интерфейсах и совместимости сигнатур
Статьи
628
Изображение носит иллюстрационный характер
Интерфейсы, впервые появившись в PHP 5, давно уже заняли прочное место в объектно-ориентированной (или всё-таки правильнее «класс-ориентированной»?) части языка.

Казалось бы — что может быть проще интерфейса? "Как бы класс, но и не класс, нельзя создать экземпляр, скорее контракт для будущих классов, содержит в себе заголовки публичных методов" — не правда ли, именно такими словами вы чаще всего отвечаете на собеседовании на дежурный вопрос о том, что такое интерфейс?

Однако не всё так просто, как может показаться начинающему программисту на PHP. Привычные аналогии не работают, руководство по языку вводит вас в заблуждение, в коде таятся неожиданные «подводные камни»…
Готовимся к собеседованию по PHP:  об интерфейсах и совместимости сигнатур
Статуэтка-логотип PHP. Источник: habrahabr.ru

Что может содержать интерфейс?
Очевидно, что публичные методы, причем без реализации: сразу после заголовка (сигнатуры) метода следует закончить его точкой с запятой:
CODE
Чуть менее очевиден (хотя и описан в мануале) тот факт, что интерфейс может содержать константы (разумеется, только публичные!):
CODE
Почему же константы в интерфейсах не получили широкого распространения в промышленном коде, хотя и используются иногда? Причина в том, что их невозможно переопределить в интерфейсе-наследнике или в классе, реализующем данный интерфейс. Константы интерфейсов — самые константные константы в мире :)
Чего не может содержать интерфейс?
Больше ничего не может. Кроме заголовков публичных методов и публичных констант.

Нельзя включать в интерфейс:

- Любые свойства;
- Непубличные методы;
- Методы с реализацией;
- Непубличные константы.

На то, собственно говоря, он и интерфейс!
Совместимость сигнатур методов
Для дальнейшего изучения интерфейсов нам с вами нужно узнать о важнейшем понятии, которое незаслуженно обойдено вниманием в мануале по PHP: о понятии «совместимости сигнатур».

Сигнатура — это описание функции (метода), включающее в себя:

1) Модификатор доступа;
2) Имя функции (метода);
3) Список аргументов, где для каждого аргумента указано:
- Тип;
- Имя;
- Значение по умолчанию;
- либо оператор «три точки».
4) Тип возвращаемого значения.

Примеры:
CODE
Предположим, что у нас есть две функции, A и B.
Сигнатура функции B считается совместимой с A (порядок важен, отношение несимметрично!) в строгом смысле, если:
Они полностью совпадают
Тривиальный случай, комментировать тут нечего.
B добавляет к A аргументы по умолчанию
A:
CODE
совместимые B:
CODE
B сужает область значений A
A:
CODE
совместимые B:
CODE
Теперь, когда мы ввели эти три простых правила совместимости определений, станет гораздо проще понять дальнейшие тонкости, связанные с интерфейсами.
Наследование интерфейсов
Интерфейсы могут наследоваться друг от друга:
CODE
Интерфейс-наследник получает от интерфейса-предка в наследство все определенные в предке методы и константы.

В интерфейсе-наследнике можно переопределить метод из родительского интерфейса. Но только при условии, что либо его сигнатура будет в точности совпадать с сигнатурой родительского, либо будет совместима (см. предыдущий раздел):
CODE
Если ли в PHP множественное наследование?
Если вам зададут такой вопрос, смело отвечайте: «да». Интерфейс может наследоваться от нескольких других интерфейсов.

Теперь вы видели всё:
CODE
Правила решения конфликтов сигнатур методов при множественном наследовании точно такие же, как мы уже видели выше:

— либо сигнатуры совпадают полностью
— либо сигнатура метода интерфейса, упомянутого в списке предков первым, должна быть совместима с сигнатурой из второго предка (да, порядок упоминания имеет значение, но это очень редкий кейс, просто не принимайте его никогда во внимание).
Тонкости реализации интерфейсов
Собственно, после всего, что вы уже видели, это уже и не тонкости, а так, мелкие нюансы.

Во-первых действительно, наследование класса от интерфейса называется реализацией. Смысл в том, что вы не просто получаете в наследство методы и константы, но обязаны реализовать те методы, которые заданы сигнатурами, наполнить их кодом:
CODE
Важный аспект, который отличает реализацию интерфейса от наследования от другого класса — это возможность реализовать в одном классе несколько интерфейсов сразу.

Как быть, если в разных интерфейсах, которые реализует класс, будет один и тот же метод (с одинаковым названием)? Смотри выше — также, как и при наследовании интерфейсов друг от друга должен соблюдаться принцип совместимости сигнатур.

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

The class implementing the interface must use the exact same method signatures as are defined in the interface. Not doing so will result in a fatal error.
Всё не так, действует тоже самое правило совместимости:
CODE
Интерфейс — это класс? Pro et Contra
Вообще-то нет. Интерфейс — это интерфейс, он отличается от класса хотя бы тем, что нельзя создать «экземпляр интерфейса».

И вообще-то да, у них в PHP очень много общего:

1. Интерфейсы, как и классы, могут находиться в пространстве имён.
2. Интерфейсы, как и классы, можно загружать через механизм автозагрузки. Функции автозагрузки будет передано полное имя интерфейса (с пространством имён).
3. В каждом интерфейсе есть предопределенная константа ThisInterface::class, содержащая его полное имя.
4. Интерфейс, как и класс, может участвовать справа в операторе instanceof.
5. Интерфейс, как и класс, может быть указан в качестве типа в тайп-хинтинге (указание типа аргумента либо возвращаемого значения функции).
Что почитать в ночь перед ответственным собеседованием?
Разумеется, мануал по языку:

php.net/manual/ru/language.oop5.interfaces.php
php.net/manual/ru/language.oop5.constants.php
php.net/manual/ru/language.constants.predefined.php

Но гораздо лучше читать тяжелые технические тексты не в последнюю ночь, а заранее.

Системный подход к самообразованию в программировании очень важен. И, по моему мнению, неплохо в начале пути в IT помогают структурировать самообучение вебинары и краткосрочные курсы. Именно поэтому я рекомендую (и немного скромно рекламирую) даже опытным разработчикам посещать разовые вебинары и курсы повышения квалификации — результат при грамотном сочетании курсов и самоподготовки всегда налицо!
Поделиться
Поделиться
Поделиться
Поделиться
Поделиться
Поделиться
Поделиться
Подписка на новости. Получайте важное первым
ПОДПИСАТЬСЯ