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

Хочется просто разобраться, что и когда лучше использовать.


Только не надо писать сообщения типа: «Интерфейс — это интерфейс… А абстрактный класс — это абстрактный класс Все просто». Так пишут везде, не давая конкретного ответа.


Желательно на конкретном примере, когда лучше использовать одно, а когда другое.
  • Вопрос задан
  • 33059 просмотров
Решения вопроса 1
try4tune
@try4tune
С точки зрения архитектуры:

Интерфейс описывает свойства. Обратите внимание на классические названия интерфейсов: Throwable, Countable, Comparable, Iterable и т.д. Возьмем, к примеру, интерфейс Rollable (катящийся), и Foldable (складывающийся).

Абстрактный класс же описывает сущность. Например, стол: Table_Abstract. Стол может быть деревянным, тогда будет Table_Wood extends Table_Abstract. Также стол может быть хирургическим: Table_Surgical extends Table_Abstract. В таком случае Table_Abstract объединяет общий свойства всех столов (скажем, площадь поверхности, наличие ножек и т.п.). А конкретный класс описывает сущность определенного типа столов.

Связью же интерфейсов и классов Вы описываете свойства. Например, стол можно катить: Table_Abstract implements Rollable. Деревянный стол, например, можно сложить: Table_Wood implements Foldable.
Ответ написан
Пригласить эксперта
Ответы на вопрос 6
sainnr
@sainnr
Как пишут умные люди (Шилдт, Троелсен) в своих умных книжках, интерфейс определяет функциональные возможности, поведение — «что именно следует делать, но не как это делать» (Г.Шилдт, Полное руководство C#). В абстрактном классе «определяется лишь самая общая форма для всех его производных классов, а наполнение ее деталями предоставляется каждому из этих классов» (там же).

Простой пример, в контексте графического редактора можно определить:
Абстрактный класс — Figure (геометрическая фигура), от него могут быть образованы классы конкретных фигур — например, Rectangle, Circle и т.д.
Интерфейс — Drawable (то, что можно нарисовать). Он может быть реализован как во всех классах конкретных фигур (Circle, Rectangle), так и в других классах, не образованных от абстрактного Figure.
Ответ написан
Комментировать
@resurection
Я бы сказал так:
Интерфейс — это возможность задать жёсткую семантику.
Абстрактный класс — это возможность вынести дублирующийся код и явно это отметить в иерархии.
Ответ написан
Комментировать
miraage
@miraage
Старый прогер
К примеру, нужно написать класс для работы с кэшем.

У нас есть класс Cache, который будет делать всю грязную работу. Он в свою очередь будет использовать библиотеку под определенный тип кэша (memcached, eaccelerator, ...). Для согласованности, библиотека должна реализовать интерфейс cacheInterface, чтобы класс Cache мог нормально работать. Вот небольшой пример.

Интерфейс для библиотеки:
Ответ написан
@Ano
Интерфейсы надо использовать, когда классы, которые должны предоставлять один и тот же интерфейс, не должны быть (или не могут быть) связаны иерархически.
Кроме того, если нужно предоставить несколько интерфейсов, а множественного наследования нет (как в PHP), то интерфейсы — единственный выход.
Ответ написан
vilonara
@vilonara
интерфейс представляет набор сигнатур функций, которые необходимо реализовать при имплементации. это не класс, это отдельная сущность. реализация методов в конкретных классах может быть абсолютно различной. общей является только сигнатура метода. в интерфейсе не может быть свойств (полей, констант).

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

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

Войдите, чтобы написать ответ

Похожие вопросы