Под «интерфейсом» в языках программирования обычно понимают обязательство класса по реализации функционала (набора методов), который описан в интерфейсе.
Интерфейсы похожи на классы, но у них есть отличительные особенности:
- интерфейс определяется с помощью ключевого слова «interface»;
- интерфейс не содержит реализации методов, а только их определения;
- все методы интерфейса должны быть публичными.
Подробнее об особенностях реализации интерфейсов в PHP можно узнать из официальной документации.
<?php interface FirstInterface { const CONST_NAME = 'Константа из MyFirstInterface'; public function firstMethod(); public function secondMethodWithParams(int $paramFirst, string $paramSecond); } interface SecondInterface extends FirstInterface { public function thirdMethod(); } class MyClass implements SecondInterface { public function firstMethod() { echo 'firstMethod()' . PHP_EOL; } public function secondMethodWithParams(int $paramFirst, string $paramSecond) { echo 'secondMethodWithParams(int $paramFirst, string $paramSecond)' . PHP_EOL; } public function thirdMethod() { echo 'thirdMethod()' . PHP_EOL; } } $object = new MyClass(); $object->firstMethod(); $object->secondMethodWithParams(1, 'two'); $object->thirdMethod(); echo $object::CONST_NAME;
В реализации механизма интерфейсов на PHP есть свои особенности, например: так как в PHP отсутствует перегрузка методов, то нельзя наследовать интерфейсы с одинаковыми наименованиями методов и разными параметрами. Приведу пример с ошибкой наследования интерфейсов из-за несовпадения сигнатур (определений) методов:
<?php interface FirstInterface { public function firstFunction(); public function secondFunction(); } interface SecondInterface extends FirstInterface { public function firstFunction(); public function secondFunction(int $age); // Возникнет ошибка, т.к. в новом варианте "secondFunction" есть параметр "$age". }
С созданием интерфейсов определились, теперь осталось разобраться как их использовать в реальных проектах. Для примера, рассмотрим следующую ситуацию: у нас есть класс «UserManager», который занимается управлением пользователями и который использует класс «SimpleNotifier» для оповещения пользователей по E-mail. Вот так выглядит его работа:
<?php class SimpleNotifier { public function send() { echo 'Отправка сообщения на E-mail.'; } } class UserManager { private $notifier; public function __construct(SimpleNotifier $notifier) { $this->notifier= $notifier; } public function do() { // другие действия. $this->notifier->send(); // другие действия. } } $manager = new UserManager(new SimpleNotifier()); $manager->do();
Чтобы «научить» класс «UserManager» отправлять сообщения не только на E-mail, но и на другие устройства, нам необходимо абстрагироваться от класса «SimpleNotifier» с помощью интерфейса. Через интерфейс можно будет передавать любой объект, который реализует функционал объявленный в этом интерфейсе. Вот как будет это выглядеть на нашем примере:
<?php interface NotifierInterface { public function send(); } class SmsNotifier implements NotifierInterface { public function send() { echo 'Отправка sms на телефон.'; } } class EmailNotifier implements NotifierInterface { public function send() { echo 'Отправка письма на E-mail.'; } } class UserManager { private $notifier; // Вместо класса (SimpleNotifier) передаем интерфейс (NotifierInterface). public function __construct(NotifierInterface $notifier) { $this->notifier = $notifier; } public function do() { // другие действия. $this->notifier->send(); // другие действия. } } $manager1 = new UserManager(new SmsNotifier()); $manager1->do(); $manager2 = new UserManager(new EmailNotifier()); $manager2->do();
Пример, конечно, крайне упрощен, но смысл должен быть понятен. Через использование интерфейсов вместо классов можно получить свободу от конкретных реализаций, что упростит наращивание и модификацию функционала.
При использовании интерфейсов, как и ООП в общем, нужно знать меру, не создавайте интерфейсы на пустом месте, их использование должно быть оправдано. Как понять, оправдано ли использование интерфейса в выбранном месте или нет? Вопрос сложный, и ответы на него приходят с опытом. Для начала, перед введением интерфейса, стоит задавать себе такой вопрос — «Планируется ли значительно наращивать функционал?».
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.