Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Абстрактный класс php
Здравствуйте, уважаемые читатели блога LifeExample, предлагаю вам ознакомиться с кратким обзором, одного из аспектов концепции ООП. Сегодня я сделаю заметку об абстрактных классах в php, а также опишу различия абстрактных классов php и интерфейсов.
Жуткие зверьки на картинке анонса, присутствуют здесь не просто так. Все дело в том, что мы будем создавать классы с монстрами для демонстрации возможностей абстрактных классов и интерфейсов.
На первом этапе программирования, новички не понимают смысла и назначения объектно-ориентированного подхода. Смысл понять можно только разрабатывая сложные проекты.
Перед разработкой структуры проекта, не плохо бы представлять, что такое абстрактный класс.
Абстрактный класс в php и абстрактный класс в любом другом языке программирования, являет собой базовый класс, не предназначенный для создания его экземпляров. Основной смысл и назначение абстрактных классов заключается в расширении возможностей его дочерних классов.
Как создать абстрактный php класс
Чтобы сделать класс абстрактным, нужно перед объявлением класса поставить идентификатор: abstract.
Для качественного усвоения материала предлагаю рассмотреть, всю цепочку взаимодействия классов, на примере упрощенного абстрактного класса Monster, характерного большинству из сегодняшних видео игр:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | abstract class Monster { public $size; // размер public $weight; // вес public $aggressive; // статус (аресивный, добрый) abstract public function demeanor($action); //поведение public function initialization($arr){ //инициализация $this->size = $arr['size']; $this->weight = $arr['weight']; $this->aggressive = $arr['aggressive']; } public function print_data(){// вывод данных echo "<br/>"; print_r($this); } } |
Задача класса состоит в реализации базовых свойств любого монстра в RPG игре.
К базовым свойствам присущим любой особи можно отнести: размер, вес, статус, местоположение и т.д.
Свойства монстра будут инициализироваться в стандартной базовой функции initialization($arr);
Обратите внимание, в классе присутствует абстрактный метод demeanor(), необходимый для задания индивидуального поведения каждого из объектов.
Идентификатор abstract, перед объявлением функции говорит о том, что данная функция должна быть обязательно определена в классе потомке.
Как использовать абстрактный класс PHP
Для использования заданных базовых свойств и методов класса Monster, нужно унаследовать их специальным идентификатором при объявлении класса потомка.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Класс описывающий первого монстра (Зомби) class Monster_Zombie extends Monster{ public function __construct($arr){ $this->initialization($arr); } //Поведение зомби public function demeanor($action){ if($action==1){ $this->aggressive="yes"; }else { $this->aggressive="no"; } return $action; } } |
Данный класс наследует все методы и свойства базового класса Monster, а также определяет новое поведение для объекта это класса.
Т.е. другими словами, дописывается логика абстрактного метода. В данном случаем в примере реализуется смена статуса монстра, при получении события равного единице. Если обработчик поведения подучает событие = 1 то монстр становится агресивным.
Представим, что мы хотим иметь два вида монстров в нашей игре с разным поведением на одно и тоже событие. С помощью абстрактных классов реализовать задуманное проще простого.
Для этого мы создаем новый класс Monster_Alien, в котором прописываем новое поведение для метода demeanor().
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Класс описывающий второго монстра class Monster_Alien extends Monster{ public function __construct($arr){ $this->initialization($arr); } public function demeanor($action){ if($action==1){ echo "<br/>Злобный звук, призывающий к бою."; } return $action; } } |
В данном случае при получении события равному единице, монстр данного класса издаст злобный звук, призывающий к бою. Конечно, никакого звука не будет, мы просто выведем в на страницу текстовое сообщение.
Абстрактный php класс и классы потомки определенны, давайте проверим их работоспособность.
Создадим объект класса Monster_Zombie, передав его конструктору необходимые данные.
1 2 3 4 5 | $Zombie=new Monster_Zombie(array( "size"=>"big_size", "weight"=>"60kg", "aggressive"=>"no", )); |
Воспользуемся базовым методом вывода данных об объекте:
1 | $Zombie->print_data(); |
Заставим нашего доброго зомби разозлиться, и передадим событие равное единице в метод обрабатывающий поведение зомби:
1 | $Zombie->demeanor(1); |
Проверим повлияли ли наши действия на зомби… 🙂
1 | $Zombie->print_data(); |
Все верно, свойство aggressive приняло значение yes и теперь данный объект является агрессивным.
Создадим монстра типа Monster_Alien:
1 2 3 4 5 | $Alien=new Monster_Alien(array( "size"=>"smal", "weight"=>"30kg", "aggressive"=>"yes", )); |
Проделаем с ним тоже, что и с Zombie:
1 2 3 | $Alien->print_data(); $Alien->demeanor(1); $Alien->print_data(); |
В результате увидим такую картину:
Итак, мы наглядно познакомились с примером использования абстрактного класса php, и теперь понимаем, что это очень удобный инструмент для расширения возможностей, того или иного объекта.
Подведем итоги и закрепим несколько важных особенностей абстрактного класса.
Абстрактные классы не должны содержать реализации метода — они только описывают интерфейс метода. Методы могут быть как обычные так и абстрактные:
Любой дочерний класс абстрактного класса должен включать в себя реализацию всех абстрактных методов родителя или сам должен быть абстрактным. Если вы этого не сделаете, PHP выдаст ошибку.
На этом я не закончу статью об абстрактных классах php, а поведаю вам уважаемые читатели об еще одном механизме расширения возможностей объектов – интерфейсах классов в PHP.
Интерфейсы в PHP
Что же такое интерфейсы, и для чего они нужны?
Интерфейсы объявляются при помощи идентификатора interface перед объявлением класса.
1 2 3 4 5 | <?php interface HitPoint { public abstract function getHitPoint(); } ?> |
Интерфейсы php очень похожи на абстрактные классы php, но в отличии от них вообще не должны содержать в себе реализации методов. Интерфейс содержит в себе только атрибуты и абстрактные методы.
Казалось бы, проигрыш перед абстрактными классами очевиден, но это еще не все особенности интерфейсов. Основным отличием и важным нюансом, при расширении возможностей дочерних классов, является возможность многочисленного наследования интерфейсов.
Другими словами, в отличии от единственности наследования абстрактно класса, мы можем наследовать столько интерфейсов, сколько захотим, а следовательно расширять возможности класса в любое время и в любом количестве.
Для того, чтобы дополнить класс интерфейсами необходимо перечислить их все, после ключевого слова implements, следующего сразу за названием класса.
1 2 3 | class Monster_Zombie extends Monster implements HitPoint , ManaPoint { function getHitPoint() } |
С таким подходом к программированию, можно в любой момент создать новый абстрактный класс, и усовершенствовать имеющиеся.
В первую очередь интерфейсы и абстрактные классы в php используют для отделения интерфейса от его реализации, это позволяет сделать код проекта более понятным и легко поддерживаемым.
P.S. Не пытайте создать RPG игру на php 🙂
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
Спасибо, единственный сайт на котором все четко объясняется
однозначно согласен с предыдушим комментарием. Спасибо большое
Спасибо. Понятно и доступно написано.
Хорошая статья! Спасибо.
Только вот на счет интерфейсов я не совсем понял. Если это возможно, то дополните, пожалуйста, статью примером с описанием использования интерфейсов.
Например, мне не понятно:
HitPoint и ManaPoint — это интерфейсы, который содержит один метод getHitPoint()? А сам метод где находится? В классе Monster_Zombie? Тогда как мы можем расширять возможности дочерних классов, если придется все методы интерфейсов описывать в самом дочернем классе? Или методы могут быть в разных классах?
Да метод находится в В классе Monster_Zombie. Чтобы сделать дочерний класс от Monster_Zombie не нужно в нем (в дочернем) реализовывать методы интерфейсов, они будут реализованы в Monster_Zombie.
2
3
4
5
interface HitPoint {
public abstract function getHitPoint();
}
?>
Писать public abstract вовсе не обязательно.
2
они только описывают интерфейс метода.
Так все же, абстрактные классы могут содержать реализацию методов или нет? =)
Могут, если очень нужно)
Не самый удачный пример, функция demeanor в одном классе модифицирует состояние объекта, а в другом что то выводит, архитектура 1 из 10
Отличная статья. Читал на PHP.SU — ничего не понял. А тут..СУПЕР!