Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%

<<< MySQL консоль || Контент выше хедера >>>

Абстрактный класс php

20.08.2012
Абстрактный класс 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();
Вызов метода абстрактного класса php

Заставим нашего доброго зомби разозлиться, и передадим событие равное единице в метод обрабатывающий поведение зомби:

1
$Zombie->demeanor(1);

Проверим повлияли ли наши действия на зомби… 🙂

1
$Zombie->print_data();

Все верно, свойство aggressive приняло значение yes и теперь данный объект является агрессивным.

Абстрактный метод класса php

Создадим монстра типа 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 выдаст ошибку.

Скачать исходник ( Скачали: 220 чел. ) 

На этом я не закончу статью об абстрактных классах 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.

  • Виталий
    1
    2
    3
    4
    5
    <?php
    interface HitPoint {
        public abstract function getHitPoint();
    }
    ?>

    Писать public abstract вовсе не обязательно.

  • Сергей
    1
    2
    Абстрактные классы не должны содержать реализации метода –
    они только описывают интерфейс метода.
    1
    Интерфейсы php очень похожи на абстрактные классы php, но в отличии от них вообще не должны содержать в себе реализации методов.

    Так все же, абстрактные классы могут содержать реализацию методов или нет? =)

    • Сергей

      Могут, если очень нужно)

  • Андрей

    Не самый удачный пример, функция demeanor в одном классе модифицирует состояние объекта, а в другом что то выводит, архитектура 1 из 10

  • Андрей

    Отличная статья. Читал на PHP.SU — ничего не понял. А тут..СУПЕР!

  • Оставить комментарий

    Подписаться на комментарии к этой статье по RSS

    Яндекс.Метрика