Может ли нам понадобиться когда-нибудь создавать объекты класса HTMLElement? Наверняка нет. Вся работа строится на базе конкретных элементов, а значит, на практике, всегда используются его наследники.
В PHP классы, объекты которых не имеют смысла, принято помечать специальным ключевым словом abstract
. Тогда никто не сможет создать объект этого класса напрямую. Только через наследников. В остальном, абстрактный класс такой же класс, со своими методами и свойствами.
<?php
abstract class HTMLElement
{
public $attributes = [];
public function __construct($attributes = [])
{
$this->attributes = $attributes;
}
public function getAttribute(string $key)
{
return $this->attributes[$key];
}
}
Абстрактные классы имеют смысл только в связке с наследованием. В большинстве случаев не нужно создавать объект от базового класса, поэтому его логично пометить как абстрактный.
Ещё одна особенность абстрактных классов связана с использованием интерфейсов. Абстрактный класс, в отличие от конкретного, не должен реализовывать интерфейсы полностью. Всё, что не реализовывает абстрактный класс, должны реализовать его наследники. Рассмотрим конкретный пример. Каждый объект, описывающий конкретный DOM-элемент, имеет текстовое представление в виде HTML-тега. Это значит, что каждый класс, наследующий HTMLElement
, должен реализовывать определённый метод, возвращающий кусок HTML. В такой ситуации можно ввести специальный интерфейс Showable (обычно так называют интерфейсы, которые отвечают за строковое представление), содержащий один метод __toString()
.
<?php
interface Showable
{
public function __toString();
}
И использование:
<?php
abstract class HTMLElement implements Showable // __toString
{
// здесь нет реализации __toString
}
С одной стороны здесь написано что абстрактный класс реализует интерфейс, с другой, так как класс абстрактный, мы можем не реализовывать Showable напрямую. Но это обязательно придётся сделать в наследниках, что нам и нужно.
Абстрактные классы могут иметь абстрактные методы, фактически это сигнатуры методов, а не сами методы. В этом смысле они становятся похожи на интерфейсы.
<?php
abstract class HTMLElement
{
abstract public function __toString();
}
С появлением абстрактных классов возникает множество новых вопросов. Когда они нужны, а когда нет? Можно ли использовать абстрактные классы вместо интерфейсов? Как совмещать их с интерфейсами?
Абстрактные классы не фундаментальная концепция и не обязательная часть ООП. Более того, в большинстве ООП языков абстрактных классов нет. Однако нельзя сказать что код на них пишется хуже, скорее наоборот. Например, в Ruby, JavaScript и Python абстрактных классов нет, но есть наследование и есть классы, которые можно было отметить как абстрактные, однако создатели этих языков не стали вводить это понятие в язык. Никогда нельзя забывать, что любые новые сущности, упрощая в одном месте, увеличивают общую сложность из-за возрастающего числа комбинаций этих сущностей друг с другом.
Общая рекомендация, не придавайте слишком много значения абстрактным классам. Используйте их тогда, когда класс имеет смысл пометить абстрактным, но не более того. Как вы увидите позже, абстрактные классы, вместе с наследованием, успешно заменяются трейтами. Причём последние гораздо более гибкий инструмент.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.