Конструктор в абстрактном классе php
Абстрактные классы в PHP
В этом уроке, мы обсудим абстрактный класс и его особенности, связанные с объектно-ориентированными методами в PHP. Кроме того, мы изучим реализацию абстрактного класса разобрав несколько примеров.
Что такое абстрактные классы и методы в PHP?
Абстрактные классы — это классы, в которых хотя бы один метод является абстрактным. Методы, объявленные абстрактными, несут, по существу, лишь описательный смысл (имеют только имя и аргументы) и не имеют тела. Таким образом, мы не можем создавать объекты из абстрактных классов. Вместо этого нам нужно создать дочерние классы, которые добавляют код в тела методов и используют эти дочерние классы для создания объектов.
Объявление абстрактных классов
Чтобы объявить абстрактный класс, нам нужно использовать ключевое слово abstract перед именем класса:
Синтаксис
Объявление абстрактных методов
Когда вы добавляете ключевое слово abstract к объявлению метода, он становится абстрактным методом. И помните, абстрактные методы не имеют тела. Поэтому фигурные скобки <> не используются.
Пример
Правила абстракции
Когда дочерний класс наследуется от абстрактного класса, применяются следующие правила:
| Видимость абстрактного метода | Видимость дочернего метода |
|---|---|
| public | public |
| protected | protected или public, но не private |
Не абстрактные методы в абстрактном классе
Неабстрактные методы могут быть определены в абстрактном классе. Эти методы будут работать так же, как обычные методы наследования.
Любой класс даже с одним абстрактным методом должен быть объявлен абстрактным. Но абстрактный класс также может иметь неабстрактные методы, к которым дочерние классы могут обращаться и использовать их напрямую, не переопределяя их.
Давайте расширим приведенный выше пример и включим в наш класс неабстрактный метод myMethod2:
Пример
Примечание: В этом основное отличие абстрактных классов от интерфейсов. Абстрактные классы могут иметь реальные методы, а интерфейсы могут иметь только объявления методов.
Пример абстрактного класса в PHP ООП
Родительский абстрактный класс:
Пример
Как создать дочерние классы из абстрактного класса?
Примечание: Дочерние классы, которые наследуются от абстрактных классов, должны добавлять тела к абстрактным методам.
Давайте создадим дочерние классы и определим в них абстрактный метод, унаследованный от родителя, greet():
Пример
Теперь мы можем создавать объекты из дочерних классов:
Пример
Полный код рассмотренного примера абстрактного класса:
Пример
Результат выполнения кода:
Заключение
Абстрактные классы важны, когда вам строго нужны дочерние классы для определения метода. В большинстве случаев абстракция используется, когда родительский класс наследуется несколькими дочерними классами, которые имеют почти одинаковое поведение. Кликните здесь, чтобы попрактиковаться в этой теме. В следующем уроке мы вернемся к концепции абстракции, но на этот раз с использованием интерфейса.
Абстрактные классы в ООП на PHP
Для этого существуют так называемые классы. Абстрактные классы представляют собой классы, предназначенные для наследования от них. При этом объекты таких классов нельзя создать.
Для того, чтобы объявить класс абстрактным, нужно при его объявлении написать ключевое слово abstract :
Попытка создать объект класса User вызовет ошибку:
Абстрактные методы
Давайте попробуем на практике. Пусть предполагается, что все потомки класса User должны иметь метод increaseRevenue ( увеличить доход ).
Этот метод должен брать текущий доход пользователя и увеличивать его на некоторую величину, переданную параметром.
Фишка тут в том, что абстрактный метод класса User заставляет программиста реализовывать этот метод в потомках, иначе PHP выдаст ошибку. Таким образом вы, или другой программист, работающий с вашим кодом, никак не сможете забыть реализовать нужный метод в потомке.
Итак, давайте попробуем на практике. Добавим абстрактный метод increaseRevenue в класс User :
Давайте теперь напишем реализацию метода increaseRevenue в классе Employee :
Проверим работу нашего класса:
Некоторые замечания
При наследовании от абстрактного класса, все методы, помеченные абстрактными в родительском классе, должны быть определены в дочернем классе.
Объявления методов также должны совпадать: количество обязательных параметром должно быть одинаковым. Однако класс-потомок может добавлять необязательные параметры, которые не были указаны при объявлении метода в родителе.
Практика
Пусть нам необходимо работать с геометрическими фигурами, например, с квадратами, прямоугольниками, треугольниками и так далее. Пусть каждая фигура будет описываться своим классом, при этом мы хотим сделать так, чтобы каждый класс имел метод для вычисления площади и метод для вычисления периметра фигуры.
Почему класс Figure абстрактный: потому что он не описывает реально существующую геометрическую фигуру и, соответственно, объект этого класса мы не будем создавать.
Почему методы getSquare и getPerimeter абстрактные: потому что каждая фигура имеет свой алгоритм вычисления площади и периметра и, соответственно, класс Figure не может написать реализацию этих методов.
Зачем нам вообще нужен класс Figure : чтобы наследовать от него и таким образом заставить всех наследников реализовать указанные методы.
Итак, напишем реализацию класса Figure :
Пусть теперь мы хотим создать класс Quadrate для описания геометрической фигуры квадрат. Как известно, у квадрата все стороны равны, поэтому для описания квадрата нам нужно задать только его ширину.
Давайте теперь унаследуем наш класс Quadrate от класса Figure :
Сейчас наша реализация класса Quadrate не рабочая, так как мы не написали реализацию абстрактных методов родителя.
Давайте сделаем это:
Давайте создадим квадрат со стороной 2 и найдем его площадь и периметр:
Усложним
Этот метод уже будет не абстрактный, а иметь реализацию, и все потомки смогут воспользоваться этим методом.
Почему мы можем написать реализацию этого метода прямо в классе Figure : потому что этот метод будет одинаковым для всех потомков.
Итак, добавим наш метод:
Применим наш метод:
Абстрактные классы в PHP
Для того, чтобы закрепить полученные знания, давайте перепишем задачу из прошлой статьи, но с использованием абстрактного класса. Начнём с класса “Car“, представляющего “абстрактный автомобиль” (файл “car.php“):
Как видите мы поставили ключевое слово “abstract“, означающее, что данный класс является абстрактным. В этом классе мы реализовали конструктор (напоминаю, что создать объект абстрактного класса нельзя). Также описали два абстрактных метода. Под описанием подразумевается определение модификатора доступа, названия функции и входных параметров. А реализовываться эти методы должны в классах-наследниках.
Теперь посмотрите, какой вид имеет класс “Легковой автомобиль“, который, в нашем случае, является уже не абстрактностью, а конкретной моделью (файл “auto.php“):
В данном примере мы реализовали два абстрактных метода, пришедших из класса “Car“, родителя для класса “Auto“.
И, наконец, давайте поиграемся с объектом “Auto“:
Как видите, мы создали объект “Auto“, вывели его свойства, воспользовались методом движения. Ничего сложного тут нет.
Возможно, что Вы скажете: “А что улучшилось-то?”. А улучшилось следующее: мы приблизились к реальности, а, следовательно, улучшили понимание структуры программы, упростили её код. Глупо и неразумно создавать некие “абстрактные объекты“, тем самым, плодя ненужные реализации “абстрактных методов“. А наш пример имеет минимум кода, без реализации абстрактности, которая, в общем-то, и не нужна.
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 14 ):
Что-то последние три темы вообще не смог понять. В принципе мне понятно про автомобили и про кошек :), что наследуется. Но что мне это даёт при создании сайта, не понятно. Возможно это всё элементарно, но до меня не доходит что-то. И комментариев нет как назло.
Да, применить это при создании сайтов очень сложно, да и вообще как-либо использовать ООП сложно. Это приходит лишь с опытом. Поэтому был записан курс по созданию движка с использованием ООП: http://srs.myrusakovr.ru/php
Спасибо. Может быть когда и пригодится. Но пока, думаю, это для меня рановато.
Я никогда не использовал ООП в создание сайта. Не подскажете когда, где и как использовать ООП на примере, кроме движка?
“А наш пример имеет минимум кода, без реализацию абстрактности, которая, в общем-то, и не нужна.” Здесь опечатка : без реализацию абстрактности.
У вас ошибка в этом предложении “Действительно, этот механизм очень классный, однако, давайте задумайся:”
Я не пойму то-ли код не рабочий то-ли я тупой
PHP абстрактные классы и интерфейсы
В этой части учебника рассказывается как работают в PHP интерфейсы и абстрактные классы, это не сильно важная тема, но всё же её знать надо.
Абстрактные классы:
По сути абстрактный класс, это шаблон класса, к примеру, это полезно когда вы точно не знаете какой код вы будите использовать внутри какого либо метода, вот пример программы.
Вот результат работы с абстрактным классов.
Как видите, мы вывели к какому классу принадлежит метод.
Интерфейсы:
Это один из элементов в ООП программирование, в том дела, что в PHP нет множественного наследования, и интерфейсы должны решить эту проблему.
Теперь покажу как их наследовать.
Важно:
Если вы наследуете интерфейс, то обязательно в классе должны прописан код каждого метода интерфейса, иначе будет ошибка.
Вот результат программы.
Всё хорошо работает.
Вывод:
В этой части учебник было показано, что такое в PHP 7 интерфейсы и абстрактные классы, как с ними работать.
Часть получилась не очень большая, так как, эта тема достаточна простая и рассказывать про неё практически нечего.
Конструктор в абстрактном классе php
PHP позволяет объявлять методы-конструкторы. Классы, в которых объявлен метод-конструктор, будут вызывать этот метод при каждом создании нового объекта, так что это может оказаться полезным, например, для инициализации какого-либо состояния объекта перед его использованием.
Замечание: Конструкторы, определённые в классах-родителях, не вызываются автоматически, если дочерний класс определяет собственный конструктор. Чтобы вызвать конструктор, объявленный в родительском классе, требуется вызвать parent::__construct() внутри конструктора дочернего класса. Если в дочернем классе не определён конструктор, то он может быть унаследован от родительского класса как обычный метод (если он не был определён как приватный).
Пример #1 Конструкторы при наследовании
class BaseClass <
function __construct () <
print “Конструктор класса BaseClass\n” ;
>
>
class SubClass extends BaseClass <
function __construct () <
parent :: __construct ();
print “Конструктор класса SubClass\n” ;
>
>
class OtherSubClass extends BaseClass <
// наследует конструктор BaseClass
>
// Конструктор класса BaseClass
$obj = new BaseClass ();
// Конструктор класса BaseClass
// Конструктор класса SubClass
$obj = new SubClass ();
// Конструктор класса BaseClass
$obj = new OtherSubClass ();
?>
В отличие от других методов, __construct() освобождается от обычных правил совместимости сигнатуры при наследовании.
Пример #2 Использование аргументов в конструкторах
Если у класса нет конструктора, или его конструктор не имеет обязательных параметров, скобки после имени класса можно не писать.
Конструкторы в старом стиле
Для классов, находящихся в собственном пространстве имён и для всех классов, начиная с PHP 8.0.0, метод, названный по имени класса, будет игнорироваться.
В новом коде всегда используйте __construct().
Определение свойств объекта в конструкторе
Начиная с PHP 8.0.0, параметры конструктора можно использовать для задания соответствующих свойств объекта. Это довольно распространённая практика — присваивать свойствам объекта параметры, переданные в конструктор, не производя никаких дополнительных преобразований. Определение свойств класса в конструкторе позволяет значительно сократить количество шаблонного кода для такого случая. Пример выше можно будет переписать следующим образом:
Пример #3 Использование определения свойств в конструкторе
Если декларация аргумента конструктора включает модификатор видимости, PHP интерпретирует его одновременно и как аргумент конструктора, и как свойство объекта и автоматически присвоит свойству значение, переданное в конструктор. При этом, если не предполагается какой-либо дополнительной логики, тело конструктора можно оставить пустым. Код конструктора выполнится после того, как все аргументы присвоятся всем соответствующим свойствам.
Не все передаваемые в конструктор аргументы должны быть свойствами объекта. В конструкторе можно задавать как обычные, так и являющиеся свойствами объекта аргументы в любом порядке. Аргументы-свойства никак не влияют на код, исполняемый в конструкторе.
Атрибуты, заданные для таких аргументов, будут применены как для них самих, так и для соответствующих свойств.
Статические методы создания объекта
Пример #4 Использование статических методов для создания объектов
Конструктор можно сделать скрытым или защищённым для предотвращения его прямого вызова. В таком случае объект класса можно будет создать только с помощью статических методов. Так как это методы того же класса, они имеют доступ ко всем его скрытым методам, даже если они относятся к разным экземплярам класса. Скрытый конструктор опционален и может присутствовать или отсутствовать по необходимости.
В примере выше три публичных статических метода демонстрируют различные способы создания экземпляра объекта.
Деструкторы
PHP предоставляет концепцию деструктора, аналогичную с той, которая применяется в других ОО-языках, таких как C++. Деструктор будет вызван при освобождении всех ссылок на определённый объект или при завершении скрипта (порядок выполнения деструкторов не гарантируется).
Пример #5 Пример использования деструктора
class MyDestructableClass
<
function __construct () <
print “Конструктор\n” ;
>
$obj = new MyDestructableClass ();
Как и в случае с конструкторами, деструкторы, объявленные в родительском классе, не будут вызываться автоматически. Для вызова деструктора родительского класса, требуется вызвать parent::__destruct() в теле деструктора дочернего класса. Подобно конструкторам, дочерний класс может унаследовать деструктор из родительского класса, если он не определён в нем.
Деструкторы, вызываемые при завершении скрипта, вызываются после отправки HTTP-заголовков. Рабочая директория во время фазы завершения скрипта может отличаться в некоторых SAPI (например, в Apache).
Попытка выбросить исключение из деструктора (вызываемого во время завершения скрипта) вызывает фатальную ошибку.
User Contributed Notes 12 notes
Consider the following example:
// create two Foo objects:
$foo = new Foo ( ‘Foo 1’ );
$bar = new Foo ( ‘Foo 2’ );
// destroy the global references to them
$foo = null ;
$bar = null ;
// we now have no way to access Foo 1 or Foo 2, so they OUGHT to be __destruct()ed
// but they are not, so we get a memory leak as they are still in memory.
//
// Uncomment the next line to see the difference when explicitly calling the GC:
// gc_collect_cycles();
//
// see also: http://www.php.net/manual/en/features.gc.php
//
// destroy the global references to them
$foo = null ;
$bar = null ;
// we now have no way to access Foo 3 or Foo 4 and as there are no more references
// to them anywhere, their __destruct() methods are automatically called here,
// BEFORE the next line is executed:
Destroying: Foo 3
Destroying: Foo 4
End of script
Destroying: Foo 1
Destroying: Foo 2
But if we uncomment the gc_collect_cycles(); function call in the middle of the script, we get:
Destroying: Foo 2
Destroying: Foo 1
Destroying: Foo 3
Destroying: Foo 4
End of script
NOTE: calling gc_collect_cycles() does have a speed overhead, so only use it if you feel you need to.



