Что такое абстрактный класс и интерфейс и когда вы будете использовать их в PHP?

Что такое абстрактный класс и интерфейс в PHP и когда вы их используете? Ответ непрофессионала с примером был бы большим, чтобы помочь моему пониманию.

5 ответов


абстрактные классы и интерфейсы не являются специфичными для PHP; они являются функциями многих современных объектно-ориентированных языков.

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

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

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

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


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

обратите внимание, что в классе может быть только один родительский класс (или абстрактный класс), но он может реализовать столько интерфейсов, сколько он должен.

но учитывая, что PHP не имеет строгого ввода и не имеет концепция проверки времени компиляции, вы можете обычно обходятся без них, в отличие от таких языков, как C++ или Java.

основной PHP требует интерфейсов для некоторых вещей. Например:

class Foo implements Countable
{
  public function count()
  {
    return 5;
  }
}

echo count(new Foo()); // returns 5

если вы удалите "реализует Счетный", PHP не будет вызывать ваш count метод. Существует много других интерфейсов, которые можно реализовать, что позволяет настраиваемым объектам вести себя аналогичным образом. Например, вы можете создать объект, который работает с foreach итерация.

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

function foo(MyInterface $bar)
{
  $bar->someMethod();
}

предполагая, что someMethod объявляется в MyInterface, тогда вам гарантировано, что вызов . (Причина, по которой это не так полезно в PHP, как на других языках, заключается в том, что подсказка типа в сигнатуре функции не будет проверяться до выполнения.)

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

interface Red {}

class Foo implements Red { }

$foo = new Foo();
if ($foo instanceof Red)
{
  // do something
}

абстрактные классы полезны, когда у вас есть много кода, который разделяется между подклассами, но сам по себе не имеет смысла. Базовый класс можно объявить абстрактным, реализовать все общие функциональные возможности и оставить остальные функции пусты. Объявив этот базовый класс абстрактным, никто никогда не сможет использовать его сам по себе.


руководство PHP объясняет это просто и предоставляет множество примеров:



интерфейс определяет набор методов, которые должен реализовать класс. Такой класс реализует интерфейс, предоставляя конкретную реализацию этих методов. Интерфейс не может содержать никакой собственной реализации; это просто набор сигнатур метода. Если я определяю интерфейс с именем ILogger, тогда я могу написать код, который использует методы, определенные в ILogger (может быть write и writeLine) для передачи сообщений в журнал. Я могу пройти в любом классе, который реализует ILogger, и клиентскому коду все равно.

абстрактный класс похож, но может реализовать некоторые методы и состояние. Абстрактные классы не могут быть созданы, и любой класс, который их расширяет, должен обеспечивать реализацию каждого abstract метод в родительском классе. Если набор классов разделяет некоторые детали реализации, но отличается в других, то вы можете определить общую реализацию в абстрактном классе, объявить различные методы абстрактными и позволить дочерним классам заполнить их с их собственной реализацией. Если мне нужен единый способ сбора системной информации, добавления меток времени и т. д. это разделяется всеми моими регистраторами, я могу выбрать создание абстрактного класса LoggerBase, который обрабатывает эти данные, обозначение write и writeLine abstract так что любые классы расширения LoggerBase просто нужно указать, как писать в свой конкретный журнал.