Пожалуйста, объясните, когда я должен использовать PHP interface
и когда я должен использовать abstract class
?
Как я могу изменить свой abstract class
в interface
?
источник
Пожалуйста, объясните, когда я должен использовать PHP interface
и когда я должен использовать abstract class
?
Как я могу изменить свой abstract class
в interface
?
Используйте интерфейс, если вы хотите заставить разработчиков, работающих в вашей системе (включая вас самих), реализовать набор методов для классов, которые они будут создавать.
Используйте абстрактный класс, когда вы хотите заставить разработчиков, работающих в вашей системе (включая вас самих), реализовать набор методов, и вы хотите предоставить некоторые базовые методы, которые помогут им в разработке своих дочерних классов.
Следует также помнить, что клиентские классы могут расширять только один абстрактный класс, тогда как они могут реализовывать несколько интерфейсов. Таким образом, если вы определяете свои контракты поведения в абстрактных классах, это означает, что каждый дочерний класс может соответствовать только одному контракту. Иногда это хорошо, когда вы хотите заставить своих программистов-пользователей следовать определенному пути. В других случаях это было бы плохо. Представьте себе, если бы PHP-интерфейсы Countable и Iterator были абстрактными классами, а не интерфейсами.
Один из подходов, который часто встречается, когда вы не знаете, какой путь выбрать (как упомянуто в разделе ниже ) - это создание интерфейса, а затем ваш абстрактный класс реализует этот интерфейс.
abstract
и как используютсяinterface
занятия, твой пост прояснил все.Различия между
Abstract Class
иInterface
:Абстрактные классы
Абстрактный класс может предоставлять некоторую функциональность, а остальное оставить для производного класса .
Производный класс может или не может переопределять конкретные функции, определенные в базовом классе.
Дочерний класс, расширенный из абстрактного класса, должен быть логически связан.
Интерфейс
Интерфейс не может содержать никаких функций . Он содержит только определения методов.
Производный класс ДОЛЖЕН предоставлять код для всех методов, определенных в интерфейсе .
Совершенно разные и не связанные классы могут быть логически сгруппированы вместе с помощью интерфейса.
источник
abstract class X implements Y
аclass X implements Y
?abstract class X implements Y
Вы заявляете, что основная функциональность X должна быть реализована в производном классе, и что абстрактный и производный класс должны содержать функции, определенные в Y, в то время какclass X implements Y
только подразумевается, что класс X должен содержать функции, определенные в Y. Если ваш интерфейс Y не предназначен для реализации каким-либо другим классом, кроме того, что XI фактически пропустит определение Y в качестве интерфейса и реализует только функции в Y как открытую / защищенную / частную абстрактную функцию, чтобы убедиться, что они реализованы в производном классе.Зачем использовать абстрактные классы? Ниже приведен простой пример. Допустим, у нас есть следующий код:
Теперь я дам тебе яблоко, а ты его съешь. Как это на вкус? На вкус как яблоко.
Что это на вкус? Ну, это не имеет особого смысла, поэтому вы не должны этого делать. Это достигается путем создания абстрактного класса Fruit и метода eat внутри него.
Абстрактный класс похож на интерфейс, но вы можете определять методы в абстрактном классе, тогда как в интерфейсе они все абстрактные. Абстрактные классы могут иметь как пустые, так и рабочие / конкретные методы. В интерфейсах определенные там функции не могут иметь тела. В абстрактных классах они могут.
Пример из реального мира:
источник
What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.
Теперь я знаю тезисы!final
ключевое слово? Отличный пост, спасибо.Рекомендуется использовать интерфейс для указания контракта и абстрактный класс как одну из его реализаций. Этот абстрактный класс может заполнить многие шаблоны, так что вы можете создать реализацию, просто переопределив то, что вам нужно или нужно, не заставляя вас использовать конкретную реализацию.
источник
Просто чтобы добавить это в микс, но, как упомянул Cletus, используя интерфейс в сочетании с абстрактным классом, я часто использую интерфейс, чтобы прояснить свое дизайнерское мышление.
Например:
Таким образом, любой, кто читает мой код (и кто знает, что такое шаблон декоратора), сразу же узнает: а) как я создаю свой синтаксический анализатор и б) сможет увидеть, какие методы используются для реализации шаблона декоратора.
Кроме того, и я могу быть здесь неосновным, не будучи программистом на Java / C ++ / etc, но здесь могут играть роль типы данных. Ваши объекты относятся к типу, и когда вы передаете их типу, это имеет значение программно. Перемещение ваших контрактных элементов в интерфейс диктует только типы, которые возвращают методы, но не базовый тип класса, который его реализует.
Уже поздно, и я не могу придумать лучшего примера псевдокода, но здесь идет:
источник
Основное отличие состоит в том, что абстрактный класс может содержать реализацию по умолчанию, а интерфейс - нет.
Интерфейс - это контракт поведения без какой-либо реализации.
источник
Кроме того, я просто хотел бы добавить, что тот факт, что любой другой язык ОО имеет какие-то интерфейсы и абстракцию, не означает, что они имеют то же значение и назначение, что и в PHP. Использование абстракции / интерфейсов немного отличается, в то время как интерфейсы в PHP на самом деле не имеют реальной функции. Они просто используются по смысловым и схемным причинам. Суть в том, чтобы проект был максимально гибким, расширяемым и безопасным для будущих расширений, независимо от того, будет ли у разработчика позже совершенно другой план использования или нет.
Если ваш английский не является родным, вы можете посмотреть, что такое абстракция и интерфейсы. И искать синонимы тоже.
И это может помочь вам как метафора:
ИНТЕРФЕЙС
Допустим, вы выпекаете новый вид пирога с клубникой и составляете рецепт с описанием ингредиентов и этапов. Только вы знаете, почему это так вкусно, а вашим гостям это нравится. Затем вы решаете опубликовать свой рецепт, чтобы другие люди тоже могли попробовать этот торт.
Дело здесь
Именно это описывает интерфейсы. Это руководство, набор инструкций, которые соблюдают содержание рецепта. То же самое, как если бы вы создавали проект на PHP и хотели бы предоставить код на GitHub или с вашими товарищами или чем-то еще. Интерфейс - это то, что люди могут делать, а что нет. Правила, которые его держат - если вы не повиноваетесь одному, вся конструкция будет нарушена.
АБСТРАКЦИИ
Чтобы продолжить эту метафору здесь ... представьте, что вы гость на этот раз съели этот торт. Тогда вы пробуете этот торт, используя рецепт сейчас. Но вы хотите добавить новые ингредиенты или изменить / пропустить шаги, описанные в рецепте. Так что будет дальше? Запланируйте другую версию этого торта. На этот раз с черными ягодами, а не с соломенными ягодами и еще ванильным кремом ... вкусно.
Это то, что вы можете считать продолжением оригинального торта. Вы в основном делаете абстракцию этого, создавая новый рецепт, потому что это немного по-другому. В нем есть несколько новых шагов и других ингредиентов. Однако в версии с черными ягодами есть некоторые детали, которые вы переняли у оригинала - это базовые шаги, которые должен иметь каждый вид этого торта. Как ингредиенты так же, как молоко - это то, что есть в каждом производном классе.
Теперь вы хотите обменяться ингредиентами и шагами, и они ДОЛЖНЫ быть определены в новой версии этого торта. Это абстрактные методы которые должны быть определены для нового пирога, потому что в пироге должен быть фрукт, но какой? Таким образом, вы берете черные ягоды на этот раз. Готово.
Итак, вы расширили торт, следовали интерфейсу и абстрагировали от него шаги и ингредиенты.
источник
Чтобы добавить к некоторым из уже превосходных ответов:
Абстрактные классы позволяют обеспечить некоторую степень реализации, интерфейсы - это чистые шаблоны. Интерфейс может только определять функциональность , он никогда не сможет ее реализовать.
Любой класс, который реализует интерфейс, обязуется реализовать все методы, которые он определяет, или он должен быть объявлен как абстрактный.
Интерфейсы могут помочь управлять тем фактом, что, как и Java, PHP не поддерживает множественное наследование. Класс PHP может расширять только один родитель. Однако вы можете сделать обещание класса реализовать столько интерфейсов, сколько захотите.
тип: для каждого реализуемого интерфейса класс принимает соответствующий тип. Поскольку любой класс может реализовывать интерфейс (или несколько интерфейсов), интерфейсы эффективно объединяют типы, которые иначе не связаны.
класс может расширять суперкласс и реализовывать любое количество интерфейсов:
Используйте интерфейс, когда вам нужно предоставить только шаблон без какой-либо реализации, и вы хотите убедиться, что любой класс, реализующий этот интерфейс, будет иметь те же методы, что и любой другой класс, который его реализует (по крайней мере).
Используйте абстрактный класс, если вы хотите создать фундамент для других объектов (частично построенный класс). Класс, который расширяет ваш абстрактный класс, будет использовать некоторые свойства или методы, определенные / реализованные:
Вот упрощенный случай / пример. Удалите все детали реализации. Например, измените свой абстрактный класс с:
чтобы:
источник
С философской точки зрения:
Абстрактный класс представляет отношение "является". Допустим, у меня есть фрукты, ну, у меня был бы абстрактный класс Fruit, который разделяет общую ответственность и общее поведение.
Интерфейс представляет отношение «должен делать». Интерфейс, по моему мнению (который является мнением младшего разработчика), должен быть назван действием или чем-то близким к действию (извините, не могу найти слово, я не являюсь носителем английского языка) скажем, IEatable. Вы знаете, что это можно съесть, но вы не знаете, что вы едите.
С точки зрения кодирования:
Если ваши объекты имеют дублированный код, это указывает на то, что они имеют общее поведение, что означает, что вам может понадобиться абстрактный класс для повторного использования кода, что вы не можете сделать с интерфейсом.
Другое отличие состоит в том, что объект может реализовать столько интерфейсов, сколько вам нужно, но вы можете иметь только один абстрактный класс из-за «проблемы с бриллиантами» (ознакомьтесь здесь, чтобы узнать почему! Http://en.wikipedia.org/wiki/ Multiple_inheritance # The_diamond_problem )
Я, наверное, забываю некоторые моменты, но надеюсь, что это прояснит ситуацию.
PS: «это» / «должен делать» принес ответ Вивека Вермани, я не хотел украсть его ответ, просто использовать термины, потому что они мне понравились!
источник
Технические различия между абстрактным классом и интерфейсом уже перечислены в других ответах точно. Я хочу добавить объяснение выбора между классом и интерфейсом при написании кода для объектно-ориентированного программирования.
Класс должен представлять сущность, тогда как интерфейс должен представлять поведение.
Давайте возьмем пример. Монитор компьютера является сущностью и должен быть представлен как класс.
Он предназначен для предоставления вам интерфейса дисплея, поэтому функциональность должна определяться интерфейсом.
Есть много других вещей, которые следует учитывать, как объяснено в других ответах, но это самая основная вещь, которую большинство людей игнорируют при кодировании.
источник
PHP
Просто хотел добавить пример, когда вам может понадобиться использовать оба. В настоящее время я пишу обработчик файлов, связанный с моделью базы данных в ERP-решении общего назначения.
Таким образом, я получаю несколько шаблонов для разных файлов и общий набор методов интерфейса с четким различием. Интерфейс дает правильную аналогию с методами доступа, а не с базовым абстрактным классом.
В дальнейшем, когда я буду делать адаптеры для различных сервисов хранения файлов, эта реализация позволит использовать интерфейс в других местах в совершенно разных контекстах.
источник