Php что такое интерфейс

от admin

Php что такое интерфейс

Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости определять, как именно они должны быть реализованы. Интерфейсы разделяют пространство имён с классами и трейтами, поэтому они не могут называться одинаково.

Интерфейсы объявляются так же, как и обычные классы, но с использованием ключевого слова interface вместо class . Тела методов интерфейсов должны быть пустыми.

Все методы, определённые в интерфейсах, должны быть общедоступными, что следует из самой природы интерфейса.

На практике интерфейсы используются в двух взаимодополняющих случаях:

  • Чтобы позволить разработчикам создавать объекты разных классов, которые могут использоваться взаимозаменяемо, поскольку они реализуют один и тот же интерфейс или интерфейсы. Типичный пример — несколько служб доступа к базе данных, несколько платёжных шлюзов или разных стратегий кеширования. Различные реализации могут быть заменены без каких-либо изменений в коде, который их использует.
  • Чтобы разрешить функции или методу принимать и оперировать параметром, который соответствует интерфейсу, не заботясь о том, что ещё может делать объект или как он реализован. Эти интерфейсы часто называют Iterable , Cacheable , Renderable и так далее, чтобы описать их поведение.

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

Замечание:

Хотя они поддерживаются, использование конструкторов в интерфейсах настоятельно не рекомендуется. Это значительно снижает гибкость объекта, реализующего интерфейс. Кроме того, к конструкторам не применяются правила наследования, что может привести к противоречивому и неожиданному поведению.

implements

Для реализации интерфейса используется оператор implements . Класс должен реализовать все методы, описанные в интерфейсе, иначе произойдёт фатальная ошибка. При желании классы могут реализовывать более одного интерфейса, разделяя каждый интерфейс запятой.

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

Замечание:

Интерфейсы могут быть унаследованы друг от друга, так же, как и классы, с помощью оператора extends.

Замечание:

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

Константы ( Constants )

Интерфейсы могут содержать константы. Константы интерфейсов работают точно так же, как и константы классов. До PHP 8.1.0 они не могли быть переопределены классом или интерфейсом, который их наследует.

Примеры

Пример #1 Пример интерфейса

// Объявим интерфейс ‘Template’
interface Template
<
public function setVariable ( $name , $var );
public function getHtml ( $template );
>

// Реализация интерфейса
// Это будет работать
class WorkingTemplate implements Template
<
private $vars = [];

public function setVariable ( $name , $var )
<
$this -> vars [ $name ] = $var ;
>

public function getHtml ( $template )
<
foreach( $this -> vars as $name => $value ) <
$template = str_replace ( ‘<' . $name . '>‘ , $value , $template );
>

// Это не будет работать
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (Template::getHtml)
// (Фатальная ошибка: Класс BadTemplate содержит 1 абстрактный метод
// и поэтому должен быть объявлен абстрактным (Template::getHtml))
class BadTemplate implements Template
<
private $vars = [];

public function setVariable ( $name , $var )
<
$this -> vars [ $name ] = $var ;
>
>
?>

Пример #2 Наследование интерфейсов

<?php
interface A
<
public function foo ();
>

interface B extends A
<
public function baz ( Baz $baz );
>

// Это сработает
class C implements B
<
public function foo ()
<
>

public function baz ( Baz $baz )
<
>
>

// Это не сработает и выдаст фатальную ошибку
class D implements B
<
public function foo ()
<
>

Пример #3 Совместимость с несколькими интерфейсами

<?php
class Foo <>
class Bar extends Foo <>

interface A <
public function myfunc ( Foo $arg ): Foo ;
>

interface B <
public function myfunc ( Bar $arg ): Bar ;
>

class MyClass implements A , B
<
public function myfunc ( Foo $arg ): Bar
<
return new Bar ();
>
>
?>

Пример #4 Множественное наследование интерфейсов

<?php
interface A
<
public function foo ();
>

interface B
<
public function bar ();
>

interface C extends A , B
<
public function baz ();
>

class D implements C
<
public function foo ()
<
>

public function bar ()
<
>

Пример #5 Интерфейсы с константами

<?php
interface A
<
const B = ‘Константа интерфейса’ ;
>

// Выведет: Константа интерфейса
echo A :: B ;

class B implements A
<
const B = ‘Константа класса’ ;
>

// Выведет: Константа класса
// До PHP 8.1.0 этот код не будет работать,
// потому что было нельзя переопределять константы.
echo B :: B ;
?>

Пример #6 Интерфейсы с абстрактными классами

<?php
interface A
<
public function foo ( string $s ): string ;

public function bar ( int $i ): int ;
>

// Абстрактный класс может реализовывать только часть интерфейса.
// Классы, расширяющие абстрактный класс, должны реализовать все остальные.
abstract class B implements A
<
public function foo ( string $s ): string
<
return $s . PHP_EOL ;
>
>

class C extends B
<
public function bar ( int $i ): int
<
return $i * 2 ;
>
>
?>

Пример #7 Одновременное расширение и внедрение

// Порядок ключевых слов здесь важен. «extends» должно быть первым.
class Two extends One implements Usable , Updatable
<
/* . */
>
?>

Интерфейс, совместно с объявлениями типов, предоставляет отличный способ проверки того, что определённый объект содержит определённый набор методов. Смотрите также оператор instanceof и объявление типов.

Php что такое интерфейс

Интерфейс определяет абстрактный дизайн, которому должен соответствовать применяющий его класс. Интерфейс определяет методы без реализации. А класс затем применяет интерфейс и реализует эти методы. Применение интерфейса гарантирует, что класс имеет определенный функционал, описываемый интерфейсом.

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

Здесь определен интерфейс Messenger . Внутри блока интерфейса в фигурных скобках определяются сигнатуры методов. Причем все эти методы могут быть только публичными, то есть с модификатором public , либо без модификатора доступа (что аналоично модификатору public):

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

Для реализации классом интерфейса применяется ключевое слово implements , после которого указывается имя применяемого интерфейса:

В данном случае класс EmailMessenger реализует интерфейс Messenger. Если класс применяет интерфейс, то он должен реализовать все методы этого интерфейса. Так, в данном случае класс EmailMessenger определяет метод send() с некоторой реализацией.

Интерфейсы также могут наследоваться от других интерфейсов:

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

Для отправки сообщения здесь определена функция sendMessage() , которая в качестве первого параметра принимает объект мессандера, а в качестве второго параметра — отправляемый текст. Причем определение первого параметра говорит, что передаваемое этому параметру значение должно реализовать интерфейс Messenger. В самой функции мы знаем, что первый параметр — это объект, который обязательно реализует интерфейс Messenger, поэтому мы можем вызвать у него метод send() для отправки сообщения:

Множественное применение интерфейсов

Класс может одновременно применять сразу несколько интерфейсов. В этом случае все интерфейсы перечисляются через запятую после слова implements . А класс должен реализовать методы всех применяемых интерфейсов:

Name already in use

php-langspec / spec / 15-interfaces.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink
  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents

Copy raw contents

Copy raw contents

A class can implement a set of capabilities — herein called a contract — through what is called an interface. An interface is a set of method declarations and constants. Note that the methods are only declared, not defined; that is, an interface defines a type consisting of abstract methods, where those methods are implemented by client classes as they see fit. An interface allows unrelated classes to implement the same facilities with the same names and types without requiring those classes to share a common base class.

An interface can extend one or more other interfaces, in which case, it inherits all members from its base interface(s).

Syntax

Constraints

An interface must not be derived directly or indirectly from itself.

Every qualified-name must name an interface type.

Semantics

An interface-declaration defines a contract that one or more classes can implement.

Interface names are case-insensitive.

The optional interface-base-clause specifies the base interfaces from which the interface being defined is derived. In such a case, the derived interface inherits all the members from the base interfaces.

Examples

Syntax

Semantics

The members of an interface are those specified by its interface-member-declaration, and the members inherited from its base interfaces.

An interface may contain the following members:

    – the constant values associated with the interface. – placeholders for the computations and actions that can be performed by implementers of the interface.

Constraints

All constants declared in an interface must be implicitly or explicitly public.

Semantics

An interface constant is just like a class constant, except that an interface constant cannot be overridden by a class that implements it nor by an interface that extends it.

Examples

Constraints

All methods declared in an interface must be implicitly or explicitly public, and they must not be declared abstract .

Semantics

An interface method is just like an abstract method.

Examples

This interface allows an instance of an implementing class to be accessed using array-like notation. This interface is defined, as follows:

The interface members are defined below:

Name Purpose
offsetExists This instance method returns TRUE if the instance contains an element with key $offset , otherwise, FALSE .
offsetGet This instance method gets the value having key $offset . It may return by value or byRef. (Ordinarily, this wouldn’t be allowed because a class implementing an interface needs to match the interface’s method signatures; however, the Engine gives special treatment to ArrayAccess and allows this). This method is called when an instance of a class that implements this interface is subscripted in a non-lvalue context.
offsetSet This instance method sets the value having key $offset to $value. It returns no value. This method is called when an instance of a class that implements this interface is subscripted in a modifiable-lvalue context.
offsetUnset This instance method unsets the value having key $offset . It returns no value.

This interface allows instances of an implementing class to be treated as a collection. This interface is defined, as follows:

The interface members are defined below:

Name Purpose
current This instance method returns the element at the current position.
key This instance method returns the key of the current element. On failure, it returns NULL ; otherwise, it returns the scalar value of the key.
next This instance method moves the current position forward to the next element. It returns no value. From within a foreach statement, this method is called after each loop.
rewind This instance method resets the current position to the first element. It returns no value. From within a foreach statement, this method is called once, at the beginning.
valid This instance method checks if the current position is valid. It takes no arguments. It returns a bool value of TRUE to indicate the current position is valid; FALSE , otherwise. This method is called after each call to Iterator::rewind() and Iterator::next() .

This interface allows the creation of an external iterator. This interface is defined, as follows:

The interface members are defined below:

Name Purpose
getIterator This instance method retrieves an iterator, which implements Iterator or Traversable . It throws an Exception on failure.

This type is the base interface for the type of any object that can be thrown via a throw statement. A user-written class cannot implement Throwable directly. Instead, it must extend Error or Exception .

This type is defined, as follows:

The interface members are defined below:

Name Purpose
__toString string ; retrieves a string representation of the exception in some unspecified format
getCode int ; retrieves the exception code
getFile string ; retrieves the name of the script where the exception was generated
getLine int ; retrieves the source line number in the script where the exception was generated
getMessage string ; retrieves the exception message
getPrevious Throwable ; retrieves the previous exception, if one exists; otherwise returns NULL
getTrace array ; retrieves the function stack trace information as an array
getTraceAsString string ; retrieves the function stack trace information formatted as a single string in some unspecified format

This interface is intended as the base interface for all traversable classes. This interface is defined, as follows:

This interface has no members.

This interface provides support for custom serialization. It is defined, as follows:

Готовимся к собеседованию по PHP: Всё, что вы хотели узнать об интерфейсах, совместимости сигнатур и не побоялись узнать

Интерфейсы, впервые появившись в PHP 5, давно уже заняли прочное место в объектно-ориентированной (или всё-таки правильнее «класс-ориентированной»?) части языка.

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

Однако не всё так просто, как может показаться начинающему программисту на PHP. Привычные аналогии не работают, руководство по языку вводит вас в заблуждение, в коде таятся неожиданные «подводные камни»…

Три предыдущие части:

Что может содержать интерфейс?

Очевидно, что публичные методы, причем без реализации: сразу после заголовка (сигнатуры) метода следует закончить его точкой с запятой:

Чуть менее очевиден (хотя и описан в мануале) тот факт, что интерфейс может содержать константы (разумеется, только публичные!):

Почему же константы в интерфейсах не получили широкого распространения в промышленном коде, хотя и используются иногда? Причина в том, что их невозможно переопределить в интерфейсе-наследнике или в классе, реализующем данный интерфейс. Константы интерфейсов — самые константные константы в мире 🙂

Чего не может содержать интерфейс?

Больше ничего не может. Кроме заголовков публичных методов и публичных констант.

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

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

Совместимость сигнатур методов

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

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

  • Модификатор доступа
  • Имя функции (метода)
  • Список аргументов, где для каждого аргумента указано:

  • Тип
  • Имя
  • Значение по умолчанию
  • либо оператор «три точки»

Предположим, что у нас есть две функции, A и B.
Сигнатура функции B считается совместимой с A (порядок важен, отношение несимметрично!) в строгом смысле, если:

Они полностью совпадают

Тривиальный случай, комментировать тут нечего.

B добавляет к A аргументы по умолчанию
B сужает область значений A

Теперь, когда мы ввели эти три простых правила совместимости определений, станет гораздо проще понять дальнейшие тонкости, связанные с интерфейсами.

Наследование интерфейсов

Интерфейсы могут наследоваться друг от друга:

Интерфейс-наследник получает от интерфейса-предка в наследство все определенные в предке методы и константы.

В интерфейсе-наследнике можно переопределить метод из родительского интерфейса. Но только при условии, что либо его сигнатура будет в точности совпадать с сигнатурой родительского, либо будет совместима (см. предыдущий раздел):

Если ли в PHP множественное наследование?

Если вам зададут такой вопрос, смело отвечайте: «да». Интерфейс может наследоваться от нескольких других интерфейсов.

Теперь вы видели всё:

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

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

Тонкости реализации интерфейсов

Собственно, после всего, что вы уже видели, это уже и не тонкости, а так, мелкие нюансы.

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

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

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

И да. Не верьте мануалу, который провозглашает:

Всё не так, действует тоже самое правило совместимости:

Интерфейс — это класс? Pro et Contra

Вообще-то нет. Интерфейс — это интерфейс, он отличается от класса хотя бы тем, что нельзя создать «экземпляр интерфейса».

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

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

Что почитать в ночь перед ответственным собеседованием?

Разумеется, мануал по языку:

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

Читать:
Default boot device missing or boot failed что делать

Похожие статьи