Здравствуйте, уважаемые читатели, предлагаю вам ознакомиться с кратким обзором, одного из аспектов концепции ООП. Сегодня я сделаю заметку об абстрактных классах в php, а также опишу различия абстрактных классов php и интерфейсов.
Жуткие зверьки на картинке анонса, присутствуют здесь не просто так. Все дело в том, что мы будем создавать классы с монстрами для демонстрации возможностей абстрактных классов и интерфейсов.
На первом этапе программирования, новички не понимают смысла и назначения объектно-ориентированного подхода. Смысл понять можно только разрабатывая сложные проекты.
Перед разработкой структуры проекта, не плохо бы представлять, что такое абстрактный класс.
Абстрактный класс в php и абстрактный класс в любом другом языке программирования, являет собой базовый класс, не предназначенный для создания его экземпляров. Основной смысл и назначение абстрактных классов заключается в расширении возможностей его дочерних классов.
Как создать абстрактный php класс
Чтобы сделать класс абстрактным, нужно перед объявлением класса поставить идентификатор: abstract.
Для качественного усвоения материала предлагаю рассмотреть, всю цепочку взаимодействия классов, на примере упрощенного абстрактного класса Monster, характерного большинству из сегодняшних видео игр:
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, нужно унаследовать их специальным идентификатором при объявлении класса потомка.
// Класс описывающий первого монстра (Зомби)
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().
// Класс описывающий второго монстра
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, передав его конструктору необходимые данные.
$Zombie=new Monster_Zombie(array(
"size"=>"big_size",
"weight"=>"60kg",
"aggressive"=>"no",
));
Воспользуемся базовым методом вывода данных об объекте:
$Zombie->print_data();
Заставим нашего доброго зомби разозлиться, и передадим событие равное единице в метод обрабатывающий поведение зомби:
$Zombie->demeanor(1);
Проверим повлияли ли наши действия на зомби… :)
$Zombie->print_data();
Все верно, свойство aggressive приняло значение yes и теперь данный объект является агрессивным.
Создадим монстра типа Monster_Alien:
$Alien=new Monster_Alien(array(
"size"=>"smal",
"weight"=>"30kg",
"aggressive"=>"yes",
));
Проделаем с ним тоже, что и с Zombie:
$Alien->print_data();
$Alien->demeanor(1);
$Alien->print_data();
В результате увидим такую картину:
Итак, мы наглядно познакомились с примером использования абстрактного класса php, и теперь понимаем, что это очень удобный инструмент для расширения возможностей, того или иного объекта.
Подведем итоги и закрепим несколько важных особенностей абстрактного класса.
Абстрактные классы не должны содержать реализации метода – они только описывают интерфейс метода. Методы могут быть как обычные так и абстрактные:
Любой дочерний класс абстрактного класса должен включать в себя реализацию всех абстрактных методов родителя или сам должен быть абстрактным. Если вы этого не сделаете, PHP выдаст ошибку.
На этом я не закончу статью об абстрактных классах php, а поведаю вам уважаемые читатели об еще одном механизме расширения возможностей объектов – интерфейсах классов в PHP.
Интерфейсы в PHP
Что же такое интерфейсы, и для чего они нужны?
Интерфейсы объявляются при помощи идентификатора interface перед объявлением класса.
<?php
interface HitPoint {
public abstract function getHitPoint();
}
?>
Интерфейсы php очень похожи на абстрактные классы php, но в отличии от них вообще не должны содержать в себе реализации методов. Интерфейс содержит в себе только атрибуты и абстрактные методы.
Казалось бы, проигрыш перед абстрактными классами очевиден, но это еще не все особенности интерфейсов. Основным отличием и важным нюансом, при расширении возможностей дочерних классов, является возможность многочисленного наследования интерфейсов.
Другими словами, в отличии от единственности наследования абстрактно класса, мы можем наследовать столько интерфейсов, сколько захотим, а следовательно расширять возможности класса в любое время и в любом количестве.
Для того, чтобы дополнить класс интерфейсами необходимо перечислить их все, после ключевого слова implements, следующего сразу за названием класса.
class Monster_Zombie extends Monster implements HitPoint , ManaPoint {
function getHitPoint()
}
С таким подходом к программированию, можно в любой момент создать новый абстрактный класс, и усовершенствовать имеющиеся.
В первую очередь интерфейсы и абстрактные классы в php используют для отделения интерфейса от его реализации, это позволяет сделать код проекта более понятным и легко поддерживаемым.