Для чего нужен interface php
Интерфейсы в PHP
В этой статье мы продолжим заниматься возможностями по ООП, которые нам предоставляет PHP. И в этот раз разберём тему интерфейсов в PHP. Если кто-то изучал C++, то те знают, что там существует множественное наследование. То есть, когда один класс наследует сразу несколько других классов. На мой взгляд, это создаёт жуткую путаницу. Поэтому было принято решение: в PHP отказаться от множественного наследования. Однако, компенсировать это как-то было надо, и тогда придумали интерфейсы. Кстати, те, кто знает Java, поймут, о чём идёт речь, так как там тоже нет множественного наследования, но имеются интерфейсы. А о том, как использовать интерфейсы в PHP я расскажу в этой статье.
Давайте разберём простой пример, создав следующий интерфейс (в файле «fileinterface.php«):
То есть данный интерфейс просто описывает работу с файлом. Соответственно, те объекты, которые должны читать из файла и записывать различные данные, обязаны реализовать интерфейс «FileInterface«.
Создадим ещё один интерфейс (в файле «client.php«):
Данный интерфейс реализует функцию клиента, то есть можно что-то купить (задаётся $id), а также что-то возвратить обратно (тоже задаётся по $id).
Думаю, тут всё прозрачно, но просто хочется добавить, что реализация должна быть для каждого метода каждого интерфейса. Она может быть пустой, но тем не менее. Про это не забывайте.
И, наконец, простой пример, который использует класс Shop:
Разумеется, другие классы, реализующие данные интерфейсы могут совсем по-другому обрабатывать их методы.
Вот и всё, что хотелось сказать по интерфейсам в PHP.
Интерфейсы в PHP
Сегодня мы поговорим об интерфейсах в PHP. Прежде чем начать разговор непосредственно об интерфейсах, давайте сначала я расскажу вам о том, какую проблему они решают и почему в них появилась необходимость.
Интерфейсы в PHP мы будем изучать на примере геометрических фигур. Пусть у нас есть прямоугольник, квадрат и круг, и, например, мы хотим вычислить их площади. Мы прекрасно помним, что для вычисления площади прямоугольника нам нужно знать длины двух соседних сторон, для квадрата – длину одной стороны, для круга – его радиус. Давайте создадим классы, которые будут описывать свойства этих фигур, а также создадим методы, для вычисления их площади.
Константы класса
Число Пи мы здесь задали в переменную, однако для таких вот постоянных вещей, которые в процессе работы программы не изменяются, лучше использовать константы. Они определяются с помощью слова const. Вот так:
Константы принято задавать в самом начале класса и называть их CAPS-ом с подчеркушками. Вот примеры того, как могут называться константы: DB_NAME, COUNT_OF_OBJECTS.
Давайте вынесем число Пи в константу.
Теперь мы можем использовать её и в других методах. Или даже в других классах, обратившись к ней через Circle::PI.
Интерфейсы
Окей, разобрались с константами и имеем в итоге 3 класса, описывающих геометрические фигуры и реализацию для вычисления их площадей. Если присмотреться, то мы видим, что во всех классах определён метод calculateSquare(), возвращающий float. Можно сказать, что у них есть что-то общее.
Допустим, мы хотели бы, чтобы у нас были фигуры, которые умеют считать свою площадь. То есть, говоря чуть более абстрактно, какие-то наши классы обязаны реализовать какой-то внешний интерфейс, а именно – иметь метод calculateSquare(), который всегда возвращает float.
Для этой задачи в PHP есть интерфейсы. Это такие «контракты», которые класс должен соблюдать, если он на это «подписался». А говоря языком программистов, классы могут реализовывать интерфейсы.
Интерфейс – это описание public методов, которые представляют собой только название метода, описание их аргументов и возвращаемый тип. Тело метода в интерфейсе не описывается.
Давайте создадим интерфейс для нашего случая.
Чтобы обязать класс реализовать этот интерфейс нужно использовать слово implements после имени класса.
Один класс может реализовывать сразу несколько интерфейсов, в таком случае они просто перечисляются через запятую.
IDE PhpStorm автоматически понимает, что наш класс реализует интерфейс и рисует слева от методов специальные иконки. Если по ним кликнуть, то нас перекинет на интерфейс.
Ну и в интерфейсе если кликнуть на такую иконку, то нам откроется список мест, где этот интерфейс реализован.
Если же мы напишем, что класс реализует какой-то интерфейс, но не реализуем его, то получим ошибку. Об этом нам даже подскажет IDE. Давайте удалим метод calculateSquare() из класса Circle. IDE любезно подчеркнёт красным строку, в которой мы говорим, что класс реализует интерфейс.
Если же мы попробуем запустить этот код, то и вовсе словим фатальную ошибку.
Так что давайте этот метод вернём обратно =)
Что ещё стоит сказать об интерфейсах – один интерфейс может содержать требования по реализации нескольких методов. Они просто перечисляются один за другим, вот так:
interface CalculateSquare
Но мы пока ограничимся одним методом calculateSquare().
Окей, так для чего это всё?
В программировании зачастую требуется проверить, что перед нами сейчас какой-то конкретный тип объектов, то есть что перед нами экземпляр какого-то класса, либо что этот объект реализует какой-то интерфейс. Для этого используется конструкция instanceof. С её помощью можно понять, является ли объект экземпляром какого-то класса, или реализует интерфейс. Эта конструкция возвращает true или false.
И снова всё верно, он не является экземпляром класса Rectangle.
А теперь давайте проверим, является ли он объектом, класс которого реализует интерфейс CalculateSquare.
Вуаля! Теперь мы перед тем как попросить какой-либо объект посчитать свою площадь, можем проверить, есть ли у него такой метод, то есть, реализует ли он соответствующий интерфейс.
Давайте добавим во все наши классы информацию о том, что они реализуют интерфейс CalculateSquare.
Давайте теперь насоздаём объектов этих классов и положим их в массив:
Теперь мы можем в цикле пройтись по ним, и для тех, которые реализуют интерфейс, посчитать площадь.
Давайте теперь уберём из класса Rectangle упоминание о том, что он реализует этот интерфейс.
class Rectangle
И снова попробуем запустить код.
Как видим, проверка успешно отработала и объект класса Rectangle был пропущен.
Полный код, полученный в ходе урока:
На этом с интерфейсами пока всё. В домашке будет ещё одна интересная функция, которая позволит вам узнать об объектах ещё кое-что.
Все о WEB программировании
WEB программирование от А до Я
Заказать сайт:
Социальные сети:
Партнеры:
Понимание использования интерфейса и абстрактного класса в PHP
Доброго времени суток. В интернете нашел интересную статью о понимании использования интерфейсов и абстрактных классов в PHP. Разницу между ними. И решил сделать перевод (но немножко дополненный), т.к. статья наглядно показывает нам, как и когда использовать интерфейсы и абстрактные классы. И так, поехали…
Интерфейс
Давайте обратимся к официальной документации PHP и посмотрим определение интерфейса:
Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости определять, как именно они должны быть реализованы.
Интерфейс в PHP определяется, как и класс за исключением вместо ключевого слова class мы указываем interface.
Все методы интерфейса являются абстрактными и открытыми – это природа интерфейса. Пример объявления интерфейса:
В интерфейсе тело метода не определено, мы определяем только имя и параметры. Теперь давайте рассмотрим, когда использовать интерфейс. Например, у нас есть следующий код:
В приведенном выше примере автор не использует интерфейс. Автор пишет в журнал, используя класс LogToFile. Но если мы захотим писать данные в журнал с использованием класса LogToDatabase. Необходимо изменить жестко закодированную ссылку на класс:
В большом проекте, когда есть несколько классов, это нужно сделать для каждого класса в ручную. Но если, мы будем использовать интерфейс, то это проблема будет решена. И нам не нужно будет менять код в ручную. Теперь давайте рассмотрим следующий код, в котором уже используется интерфейс:
Теперь, если мы записываем данные не LogToDatabase, а с помощью LogToFile нам не нужно менять метод конструктора в ручную. В методе конструктора мы вводим интерфейс. Поэтому, если у вас есть несколько классов и вы переключаетесь с одного класса на другой, вы получите тот же результат без изменения каких-либо ссылок на классы.
В приведенном выше примере автор пишет данные в журнал, используя LogToDatabase, и теперь, если захочет записать данные в журнал, используя LogToFile, то можно просто заменить:
Таким образом мы получаем результат без изменения других классов.
Абстрактный класс
Давайте посмотрим официальную документацию PHP для того, чтобы понять что такое абстрактный класс.
PHP 5 поддерживает определение абстрактных классов и методов. Объекты классов, определенных как абстрактные, не могут быть созданы, и любой класс, который содержит по крайней мере один абстрактный метод, должен быть определен как абстрактный. Методы, объявленные абстрактными, несут, по существу, лишь описательный смысл и не могут включать реализацию.
Когда использовать абстрактный класс?
Например, давайте рассмотрим класс Tea
Теперь рассмотрим класс Coffee:
В приведенных выше классах три метода addHotWater(), addSugar(), addMilk() одинаковы. Поэтому мы должны удалить дублированный код:
Автор создает абстрактный класс и называет его Template. В этом классе определяет три метода addHotWater (), addSugar () и addMilk () и создает абстрактный метод с именем addPrimaryToppings.
Теперь, если создавать класс Tea его необходимо делать расширенным для класса Template, тогда мы получаем три определенных метода и должны определить метод addPrimaryToppings ().
Для чего нужен interface php
Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости определять, как именно они должны быть реализованы. Интерфейсы разделяют пространство имён с классами и трейтами, поэтому они не могут называться одинаково.
Все методы, определённые в интерфейсах, должны быть общедоступными, что следует из самой природы интерфейса.
На практике интерфейсы используются в двух взаимодополняющих случаях:
Интерфейсы могут определять магические методы, требуя от реализующих классов реализации этих методов.
Хотя они поддерживаются, использование конструкторов в интерфейсах настоятельно не рекомендуется. Это значительно снижает гибкость объекта, реализующего интерфейс. Кроме того, к конструкторам не применяются правила наследования, что может привести к противоречивому и неожиданному поведению.
implements
Класс может реализовать два интерфейса, которые определяют метод с тем же именем, только если объявление метода в обоих интерфейсах идентично.
Класс, реализующий интерфейс, может использовать для своих параметров имя, отличное от имени интерфейса. Однако, начиная с PHP 8.0, в языке поддерживаются именованные аргументы, и вызывающий код может полагаться на имя параметра в интерфейсе. По этой причине настоятельно рекомендуется, чтобы разработчики использовали те же имена параметров, что и реализуемый интерфейс.
Интерфейсы могут быть унаследованы друг от друга, так же, как и классы, с помощью оператора extends.
Класс, реализующий интерфейс, должен объявить все методы в интерфейсе с совместимой сигнатурой.
Константы ( Constants )
Интерфейсы могут содержать константы. Константы интерфейсов работают точно так же, как и константы классов. До PHP 8.1.0 они не могли быть переопределены классом или интерфейсом, который их наследует.
Примеры
Пример #1 Пример интерфейса
Пример #2 Наследование интерфейсов
interface A
<
public function foo ();
>
// Это сработает
class C implements B
<
public function foo ()
<
>
// Это не сработает и выдаст фатальную ошибку
class D implements B
<
public function foo ()
<
>
Пример #3 Множественное наследование интерфейсов
interface A
<
public function foo ();
>
interface B
<
public function bar ();
>
class D implements C
<
public function foo ()
<
>
public function bar ()
<
>
Пример #4 Интерфейсы с константами
interface A
<
const B = ‘Константа интерфейса’ ;
>
// Выведет: Константа интерфейса
echo A :: B ;
class B implements A
<
const B = ‘Константа класса’ ;
>
// Выведет: Константа класса
// До PHP 8.1.0 этот код не будет работать,
// потому что было нельзя переопределять константы.
echo B :: B ;
?>
Пример #5 Интерфейсы с абстрактными классами
Пример #6 Одновременное расширение и внедрение
Интерфейс, совместно с объявлениями типов, предоставляет отличный способ проверки того, что определённый объект содержит определённый набор методов. Смотрите также оператор instanceof и объявление типов.
Зачем нужны абстрактные классы и интерфейсы в php?
Простой 15 комментариев
Абстрактный класс- это реальные инструменты, необходимые для
1) повышения Читабельности кода
2) Уверенности в том, что делает код
Далее уже сделать имплементацию этого интерфейса на всех наследниках класса Tariff где нужно, и не парится, что через какое-то время другой разработчик создаст новую реализацию тарифа и с твоего кода посыпятся баги
Да, носят чисто декларативный характер
Ruslan Ruslanov, не для упрощения кода, а для стандартизации взаимодействия между объектами. Если на вашем компе есть юсб вход, то и мышка вам нужна с таким же интерфейсом. В данном случае юсб это стандарт для ваших объектов, соблюдая который вы можете взаимодействовать их.
Попробуйте написать классы для этого примера.
С интерфейсами самый простой кейс:
1) Пишем какую-то функцию, которая принимает в качестве аргумент интерфейс.
2) Функция работает с методами интерфейса и получает какой-то результат.
3) Где-то есть отдельная логика, выбора конкретной реализации класса, который выполняет интерфейс.
Т.е. допустим, у нас есть онлайн-касса и есть 20 методов платежей. Сама онлайн-касса работает с интерфейсом проводки платежа, а как проводить платежи реализовано в конкретных классах платежных систем.
Из минусов, иногда приходиться весьма «изящно» натягивать вещи, которые не очень ложатся на методы интерфейса, чтобы доп-функциональность работала согласно «верному пути» архитектора.
Абстрактный класс. ну допустим, мы далем абстрактный класс DTO, который выполняет методы to_string и normalize. Наследуюясь от этого абстрактного класса, мы во всех DTO получаем методы to_string и normalize. Плюс защищаемся от того, что кто-то решит нам запороать этот абстрактный класс, либо «решит» что-то сломать в своем DTO
Ну вообще, это все нужно, если ты пишешь хороший проект на Symfony командой. Если это какой-то бложит или небольшой новостник, тебе это все не нужно.
Абстрактные классы в основном используются в том случае, если какую-то часть кода можно описать в родительском классе, но для того чтоб эта часть приобрела смысл, нужна конкретика: дополнить общую картину подробностями в виде методов или полей. Если вы присмотритесь к абстрактным классам в современных фреймворках, то увидите что сам по себе абстрактный класс не имеет смысла. Например, если создать объект такого класса оператором new, то этому объекту всё равно будет чего-то не хватать и именно это что-то и добавляют дочерние классы.
> и в этом случае интерпретатор будет знать как перебрать коллекцию в цикле foreach.
Я бы сказал, что, как раз знать как перебрать он не будет, но сможет, тем не менее, заставить её перебраться. 🙂 Это немного тонкая разница, но тем не менее.
1. Абстрактный класс нельзя создать, только создать обьект от наследуемого класса
2. Абстрактный класс может содержать реализацию, в отличии от интерфейса
3. Абстрактный класс может содержать абстрактные методы, которые необходимо будет реализовать в дочерних классах
4. Можно имплементировать сразу несколько интерфейсов, а наследовать только от одного класса.
5. Трейты очень хорошо комбинируются с интерфейсами
Осознание зачем это нужно, прийдёт к вам в процессе использования)) Почитайте также про SOLID, и попробуйте реализовать эти принципы без абстракций и интерфейсов)
P.S. Домашнее задание
Есть три класса. Квадрат, Прямоугольник, Круг. И класс Ящик. Мы добавляем в ящик, произвольные наборы из фигур, и нужно посчитать площадь всех фигур в ящике.
Ruslan Ruslanov, Зачем указывать квадрату две стороны? Это же квадрат, у него стороны равны
Плюс врывается обезумевший заказчик, и хочет добавить треугольник, а также возможность задавать цвет, но только для круга и квадрата
P.S. Домашнее задание
Есть три класса. Квадрат, Прямоугольник, Круг. И класс Ящик. Мы добавляем в ящик, произвольные наборы из фигур, и нужно посчитать площадь всех фигур в ящике.
))) Я вас удивлю, но условия в жизни меняются чаще чем хотелось бы, и не всегда они меняются на те что ожидалось или хотелось. Для этого люди и придумывают разные практики и методики. Чтоб при очередном таком изменении, минимально переписывать код. А дальше уже каждый ищет для своей задачи эту золотую середину. Я считаю что нужно знать как можно больше подходов, чтоб выбрать оптимальный.
Вот рекомендую это изучить, а как поймете, о чём речь и для чего это всё. Тогда можно уже смело отбрасывать всё и делать как хочется)
https://ota-solid.now.sh/
P.S. В любом случае, это очень часто спрашивают на собеседованиях, так что если ваши планы более грандиозны, чем маленький самописный проект, который вы сами разрабатываете и не меняете в нём ничего, то стоит подготовится
но тогда просто будет сложно работать.
он (абстрактный класс) носит чисто декоративный характер, нужен для ограничения действий разработчика, удобства разработки и вообще это лишь «сахар?.