Абстрактный класс может иметь и не иметь абстрактных методов, но интерфейс имеет только реализованные методы. Итак, какова разница и преимущество использования интерфейса, если мой абстрактный класс имеет все его методы, помеченные как абстрактные?
Абстрактный класс допускает «частичную реализацию» (см. Шаблон шаблона шаблона), но в этом случае, если все методы являются абстрактными, вы не видите этого преимущества. Еще одна вещь, которую вы можете сделать, это включить поля, вы не ограничены только методами.
Помните, что существует концептуальная разница между «абстрактным методом» и контрактом, определенным интерфейсом. Абстрактный метод должен быть переопределен подклассом, который выполняется через реализацию наследования. Любые полиморфные вызовы (downcasting) потребуют одного суперкласса для каждого класса или он попадет в проблему наследования алмазов. Такая древовидная структура, основанная на наследовании, типична для дизайна OO.
В отличие от этого, интерфейс обеспечивает подпись контракта для выполнения. Вы можете выполнять многие требования к интерфейсу, пока вы сохраняете подпись, поскольку нет необходимости возвращать иерархию классов для поиска других реализаций. Интерфейсы на самом деле не полагаются на полиморфизм, чтобы сделать это, это основано на контракте.
Другое замечание: у вас могут быть «защищенные» абстрактные методы, нет смысла делать что-то в интерфейсе (на самом деле это незаконно).
Если abstract class
имеет все свои методы, определенные как abstract
то вы должны определить его тело в любых подклассах и отображать подобное поведение как interface
.
Выгода :
Используя interface
вместо abstract
класса, вы можете implement
более одного interfaces
при использовании abstract
класса, который вы можете расширить только one
класс за раз.
РЕДАКТИРОВАТЬ
Другое отличие, которое я нашел об этом, – это abstract
класс, который может иметь constructor
а interface
не может быть.
REF: что такое использование конструктора в абстрактном классе в php
Интерфейсы и абстракция
Реальная сила использования может быть раскрыта в огромных API-интерфейсах с огромным количеством классов, которые следуют продуманной гибкой структуре будущего кодирования. Может ли это случиться или нет – вы никогда не знаете, будет ли расширен код. Интерфейсы просто используются по смысловым соображениям. Представьте, вы распространяете устаревшую версию API и выполняете задание по редактированию / изменению / внедрению / обновлению / улучшению / расширению / модификации кода, чтобы обновить его, независимо от причины. В конечном итоге вы будете разочарованы, если не подумаете.
Малые API-интерфейсы могут быть созданы без интерфейсов, и большинство людей считают, что интерфейсы не нужны. Но тогда они теряют гибкость, как только они становятся больше. Они предоставляют вам контракт с классами, который напоминает вам, что необходимо, и чтобы сохранить обзор. Интерфейсы должны иметь общедоступные методы, если у вас есть защищенные или частные, просто верните их в открытый метод класса с реализованным интерфейсом.
Как вы уже объяснили, интерфейсы требуют, чтобы определенные методы были реализованы, абстрактные классы не требуют этого, так как вы, скорее всего, их расширяете. Методы могут быть переопределены, и абстрактные методы ДОЛЖНЫ быть определены в дочерних классах. Методы, упомянутые в интерфейсе, говорят только о том, что эти классы, имеющие контракт с интерфейсом, должны иметь эти определения. Это может быть несколько интерфейсов, вы не наследуете их, как вы делали бы это с абстрактными классами.
Подумайте так
Логика в этом заключается в том, чтобы предсказать будущее в том, что вы планируете строить. Будь то в архитектуре, инфраструктуре или массовом производстве на заводах. Точно так же, как вы заказываете такие вещи, как закладки, книги, изображения в папке. Это займет больше времени, чтобы найти конкретный образ, если вы его не отсортировали. Я указываю на семантическое использование абстракции и интерфейса.
Я покажу вам типичную структуру для запуска API с упрощенным содержанием, в котором интерфейсы и абстрактные классы имеют реальную ценность для будущего расширения.
/* Considering, this project will be widely expanded up to huge complexity. This is a flexible base structure, for developers working in team. Imagine there could be lots more variation of styles for certain purposes. */ // OOP STRUCT // You might want to define multiple interfaces to separate the project interface iString { // These methods MUST be defined or else the developer receives an error public function getContent(); public function description($desc); } /* Devs might want to add an additional method later on. Traits are useful for quick use. (optional) */ trait desc { private $desc; public function description($desc) { return $this->desc; } } /* This is the base class for the content which requires a declaration of methods being described in the interface */ class contents implements iString { use desc; // use the method defined in a trait private $str; public function __construct($str) { $this->str = $str; } public function getContent() { return $this->str; } } /* Devs often consider abstract classes as the real base of the whole project. Abstract classes allow the use of methods that can be modifed in derived classes. Interfaces can't do that */ abstract class stylize implements iString { use desc; private $str; // This typehint below makes sure that this value is assigned on interface public function __construct(iString $str) { $this->str = $str; } public function style() { return $this->str->getContent(); } abstract public function getContent(); } // EXTENDED CLASSES class bold extends stylize { // Extended classes have to define abstract methods inherited from an abstract class. Non-abstract methods are not needed. public function getContent() { return "<strong>".parent::style()."</strong>"; } } class underline extends stylize { public function getContent() { return "<u>".parent::style()."</u>"; } } class upperCase extends stylize { public function getContent() { return strtoupper(parent::style()); } } // PROCEDURAL OUTPUT // A tiny shortcut $e = function($desc,$str) { echo $desc.": ".$str->getContent()."<br>"; }; // Content being used $content = new contents('Hello World.'); $e("Normal",$content); // Content being styled $bold = new bold($content); $underline = new underline($content); $upper = new upperCase($content); // Renders content with styles $e("Bold",$bold); $e("Underline",$underline); $e("Uppercase",$upper);
Вывод
Применение стилей текстового содержимого в качестве примера, вероятно, недостаточно привлекательно. Но кроме того, он остается прежним – если он делает то, что он должен делать, то это делается. Как будто я бы построил расширяемый API конфигурации электронной почты в качестве модуля для CMS. Эта структура имеет семантический процесс в правильном кодировании.
Tipps
Я предлагаю вам продолжать учиться в небольших проектах с такой моделью, даже если вы считаете, что интерфейсы не стоят того. Продолжайте делать это, пока не получите его внутри. Мой личный совет для вас: если вы думаете, что не знаете, с чего начать и какой проект попробовать, попробуйте примеры из реального мира, просто следуйте этой логике:
Транспортные средства (абстрактный класс) -> Ferrari (расширенный класс) -> Грузовик (расширенный класс) оба колеса (собственность) оба должны иметь возможность управлять (методом) они выполняют гоночную гонку на улице (абстрактный метод) один - медленный (расширенное свойство) один красный - синий (расширенное свойство) и позже приходит третий, и его поезд (расширенный класс) кто собирается выиграть (какой-то метод) Создавайте все транспортные средства и сохраняйте привилегии по интерфейсу и абстракция. ...что-то вроде этого...
Как правило, классы, содержащие огромные тела, должны быть разделены в одиночных файлах + включать эти + определить пространство имен. Еще одна стена кода заставит вас или кого-то еще устать. Используйте Eclipse , лучшее приложение для поддержки ООП.
Кроме того, если он подходит для вашего проекта, используйте phUML, если у вас Linux Ubuntu . Он генерирует графическую диаграмму для вашей текущей сборки, если у вас много связанных классов.
phUML – это API в PHP на основе UML. Это проект с открытым исходным кодом, который генерирует любые визуальные схемы практически для любого популярного языка программирования. Я использую его много, а не только для PHP. Просто клонируйте его в Github или загрузите с сайта dasunhegoda.com и следуйте инструкциям по установке.
Это может вас заинтересовать: Typehinting на интерфейсах