Интерфейсы interface
В интерфейсах определяют методы без реализации, от интерфейсов наследуются классы в которых обязательно должны быть реализованы все методы интерфейса, иначе получим ошибку. Класс наследованный от интерфейса может расширятся за счет собственных свойств и методов которых нет в интерфейсе, при этом ошибок не будет. Применение интерфейса гарантирует, что класс имеет определенный набор методов, описываемых интерфейсом.
Особенности интерфейсов
- Нельзя создать объект интерфейса
- Все методы интерфейса должны быть объявлены как
public
- Все методы интерфейса не должны иметь реализации
- У интерфейса могут быть только методы, но не свойства
- Нельзя делать интерфейс и класс с одним и тем же названием
Реализация интерфейсов
Интерфейс определяется с помощью ключевого слова interface
, за которым следует имя интерфейса и блок кода интерфейса в фигурных скобках:
interface iMessenger {
}
Здесь определен интерфейс iMessenger
. Обычно имя интерфейса начинается со строчной буквы i
, но это условность.
Внутри блока интерфейса в фигурных скобках определяются сигнатуры методов. Причем все эти методы могут быть только публичными, то есть с модификатором public
, либо без модификатора доступа (что аналоично модификатору public
):
interface iMessenger {
function send();
}
Интерфейсы могут содержать лишь сигнатуры методов - наазвания функций и список параметров в скобках, после которого идет точка с запятой. Так, в данном случае объявлен метод send()
. Он не имеет реализации - конкретную реализацию определит класс, который реализует этот интерфейс.
Для реализации классом интерфейса применяется ключевое слово implements
, после которого указывается имя применяемого интерфейса:
<?
// интерфейс
interface iMessenger
{
function send();
}
// класс наследник интерфейса
class EmailMessenger implements iMessenger
{
// количество и название методов в классе, должно быть эквивалентно интерфейсу, иначе получим ошибку
function send()
{
echo "Отправка сообщения на e-mail";
}
}
// объект класса
$outlook = new EmailMessenger();
$outlook->send();
В данном случае класс EmailMessenger
реализует интерфейс iMessenger
. Если класс применяет интерфейс, то он должен реализовать все методы этого интерфейса. Так, в данном случае класс EmailMessenger
определяет метод send()
с некоторой реализацией.
Интерфейсы также могут наследоваться от других интерфейсов:
<?
// интерфейс
interface iMessenger
{
function send();
}
// интерфейс
interface iEmailMessenger extends iMessenger
{
}
// класс наследник интерфейса
class SimpleEmailMessenger implements iEmailMessenger
{
function send()
{
echo "Отправка сообщения на email.";
}
}
// объект класса
$outlook = new SimpleEmailMessenger();
$outlook->send();
Когда нам могут понадобиться интерфейсы? Интерфейс - это контракт, который говорит, что класс обязательно реализует определенный функционал. И мы можем использовать это в своей программе. Например, определим следующий код:
<?
// интерфейс
interface iMessenger
{
function send($message);
}
// метод
function sendMessage(iMessenger $messenger, $text)
{
$messenger->send($text);
}
// класс наследник интерфейса
class EmailMessenger implements iMessenger
{
function send($message)
{
echo "Отправка сообщения на email: $message";
}
}
// объект класса
$outlook = new EmailMessenger();
sendMessage($outlook, "Hello World");
Для отправки сообщения здесь определена функция sendMessage()
, которая в качестве первого параметра принимает объект мессандера, а в качестве второго параметра - отправляемый текст. Причем определение первого параметра говорит, что передаваемое этому параметру значение должно реализовать интерфейс iMessenger
. В самой функции мы знаем, что первый параметр - это объект, который обязательно реализует интерфейс iMessenger
, поэтому мы можем вызвать у него метод send()
для отправки сообщения:
function sendMessage(iMessenger $messenger, $text) {
$messenger->send($text);
}
Интерфейсы похожи на абстрактные классы, обе сущности могут определять методы без реализации, которые реализуются в других классах. Только интерфейсы, не могут как абстрактные классы, иметь свойства, неабстрактные методы, конструкторы.
Множественное применение интерфейсов
Класс может одновременно применять сразу несколько интерфейсов. В этом случае все интерфейсы перечисляются через запятую после слова implements
. А класс должен реализовать методы всех применяемых интерфейсов:
<?
// интерфейс
interface iCamera
{
function makeVideo();
function makePhoto();
}
// интерфейс
interface iMessenger
{
function sendMessage($message);
}
// класс наследник двух интерфейсов
class Mobile implements iCamera, iMessenger
{
function makeVideo()
{
echo "Запись видео";
}
function makePhoto()
{
echo "Съемка фото";
}
function sendMessage($message)
{
echo "Отправка сообщения $message";
}
}
// объект класса
$iphone = new Mobile();
$iphone->makePhoto();