Абстрактные классы. Часть 2. Абстрактные классы и интерфейсы
В предыдущем посте этой серии я прошел через:
- основы абстрактных классов,
- как их реализовать,
- и предоставил рабочие примеры кода.
И хотя я думаю, что понимание абстрактных классов является ключом к созданию прочной основы для объектно-ориентированного программирования, я часто вижу, что это может сбивать с толку, когда дело доходит до сравнения их с интерфейсами и понимания, когда их использовать.
Абстрактные классы и интерфейсы
Итак, в этом посте я поделюсь:
- быстрое освежение информации о том, что такое интерфейсы,
- что такое абстрактные классы,
- а затем, как узнать, когда использовать один над другим.
Это не должна быть статья, посвященная написанию кода, но она должна помочь узнать, когда писать код определенного типа, чтобы помочь лучше организовать ваши проекты.
1 Интерфейсы
Вспомните, что когда дело доходит до интерфейсов, мы также используем термин «программирование интерфейса», имея в виду, что интерфейс определяет методы, которые должен реализовать класс для выполнения «контракта» с указанным интерфейсом.
Код, используемый для демонстрации базового интерфейса, был таким:
<?php
interface iCache
{
public function set($key, $value);
public function get($key);
public function has($key);
}
Но помните, цель интерфейса не в том, чтобы определять после того, как код написан. Вместо этого это инструмент, используемый для разработки того, какие классы должны быть реализованы, если они следуют определенной парадигме или им требуется определенный набор функций.
То есть, если вы собираетесь разрабатывать набор классов, которые работают с кэшированием, вы не пишете сначала классы. Сначала вы пишете интерфейс, а затем классы реализуют этот интерфейс.
Идея состоит в том, что любой класс, реализующий интерфейс, будет гарантированно иметь эти функции.
2 абстрактных класса
Абстрактные классы, с другой стороны, позволяют нам делать две вещи:
- реализовать функциональность, которую могут использовать подклассы,
- реализовать сигнатуры методов, которые должны реализовать подклассы.
Сначала это может показаться немного неуместным, но подумайте об этом:
Когда у вас есть класс определенного типа, который будет иметь согласованную функциональность независимо от подкласса, функциональность переходит в абстрактный класс. Когда другие методы должны иметь свою реализацию метода, вы просто предоставляете сигнатуру метода и помечаете ее как abstract.
Вот пример из предыдущего поста:
Итак, это подводит нас всех к предыдущим примерам и предыдущим вещам, на которых нам нужно сосредоточиться в отношении интерфейсов и абстрактных классов, но для некоторых это все еще не дает ясности.
В частности, это все еще не отвечает на вопрос: как мы решаем, когда использовать абстрактный класс, а когда использовать интерфейс?
На первый взгляд это может показаться немного запутанным, но есть несколько вещей, которые помогут вам принять решение.
Когда мы используем каждый?
Помните, что когда дело доходит до объектно-ориентированного программирования, мы можем разбить его на три различных направления:
- Классы представляют вещь. Вы можете считать это существительным.
- Атрибуты или свойства подобны прилагательным. Они описывают объект или что-то, что объект может содержать.
- Методы или функции подобны глаголам. Они описывают, что может сделать их объект.
Теперь, когда дело доходит до интерфейса, подумайте о том, что делает интерфейс: он описывает, без реализации, что может делать объект. А когда дело доходит до абстрактного класса, он описывает, что представляет собой объект во время выполнения.
Другими словами, хорошее эмпирическое правило состоит в том, что если вам нужно предоставить набор поведений для объекта, интерфейс — это то, что вам нужно. Если вам нужно описать, что такое объект, используйте абстрактный класс.
Для абстрактных классов я бы также пошел дальше и сказал, что это помогает описать базовый уровень данных, которые описывают объект или то, что он может хранить в дополнение к базовому уровню функциональности.
Есть пример?
Как и в случае с большей частью контента в каждом из этих постов, я стараюсь приводить примеры, даже если это не делается специально в коде. Возможно, это поможет объяснить это еще больше:
- Интерфейсы не имеют реализации. Они только гарантируют, что класс будет делать.
- Абстрактные классы должны иметь базовый уровень реализации. Это должно представлять то, что класс может содержать и делать, но не является полным. Они требуют немного большей реализации от подкласса.
Когда вы работаете с объектно-ориентированным кодом, я надеюсь, что это поможет дать некоторые рекомендации относительно того, когда что использовать. Если нет, не стесняйтесь оставлять комментарии (на это у участников есть разрешение :).
Кроме того, мы увидим это на практике, когда приступим к написанию объектно-ориентированного кода (особенно для WordPress, но не всегда).