PHP: полиморфизм, инкапсуляция и SOLID

Решил написать краткую напоминалку себе и другим, а то в просторах инета любят расписывать замудрено.

Советую начать с статьи про полиморфизм и инкапсуляцию и ниже закрепить знания + прочитать про SOLID.

Полиморфизм в PHP

Что такое полиморфизм в PHP:

  1. возможность использовать вместо экземпляров родительского класса экземпляры подкласса
  2. возможность использовать один и тот же метод для объектов разных классов

Пример: пользователь хочет отследить последние обновления публикаций, причем ему не важно, будут это статьи или новости или что-то еще.

abstract class Publication {
    // определяем правило, что все публикации должны печататься, т.е. иметь метод do_print()
    abstract protected function do_print();
    // испольузем final чтобы инкапсулировать логику работы данного метода 
    final protected function getClassName(){ return __CLASS__; }
}

class News extends Publication {
   // переопределяем абстрактный метод печати
   public function do_print() {
       echo 'Новость';
   }
}
class Announcement extends Publication {
    // переопределяем абстрактный метод печати
    public function do_print() {
        echo 'Объявление';
    }
}

//Наполняем массив публикаций объектами, производными от Publication
$publications[] = new News();
$publications[] = new Announcement();
// пример полиморфизма:
foreach ($publications as $publication) {
    if ($publication instanceof Publication) { // Если мы работаем с наследниками Publication
        $publication->do_print(); // то мы можем смело выводить данные на печать
    } else {
        //исключение или обработка ошибки
    }
}
function printPublicationName(Publication $publication){
    // пример использования метода, который инкапсулирован:
    $publication->getClassName();
}
printPublicationName(new News());
printPublicationName(new Announcement());

Инкапсуляция в PHP

Инкапсуляцию можно сравнить с работой автомобиля с точки зрения типичного водителя. Многие водители не разбираются в подробностях внутреннего устройства машины, но при этом управляют ею именно так, как было задумано. Пусть они не знают, как устроен двигатель, тормоз или рулевое управление, — существует специальный интерфейс, который автоматизирует и упрощает эти сложные операции. Сказанное также относится к инкапсуляции и ООП — многие подробности "внутреннего устройства" скрываются от пользователя, что позволяет ему сосредоточиться на решении конкретных задач. В ООП эта возможность обеспечивается классами, объектами и различными средствами выражения иерархических связей между ними.

В программном смысле этого слова, инкапсуляция - это скрытие переменных в классе от пользователя. Т.е. все переменные (свойства) класса Вы делаете скрытыми (private), а методы открытыми (public). Т.е. можно будет взаимодействовать со свойствами класса через методы.
Прелесть данного подхода в том, что в методах можна вставить код для проверки всяких ошибок, и потом о них не думать, когда вызывается метод.

Касательно SOLID

Хочется внести ясность в приципы Liskov substitution и Dependency inversion, т.к. теоретически сложно понять в чем их отличие, но я попробую.

Liskov substitution гласит: 

Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.

Это означает, что если мы вызываем метод определенного класа, то этот класс должен быть замещаем (полиморфизм).

Подклассы не могут замещать поведения базовых классов. Подтипы должны дополнять базовые типы.

Это означает, что мы должны расширять базовый класс (используя extend), но переопределять методы базового класса нельзя (инкапсуляция), поэтому в примере выше, мы написали final, см. выше).

Dependency inversion гласит:

Зависимости внутри системы строятся на основе абстракций

Означает, что класс Publication должен быть абстрактным или интерфейсом, и затем именно его как тип данных, нужно объявлять при передаче аргемента в функции (полиморфизм - см. выше вызовы printPublicationName).

Модули верхнего уровня не зависят от модулей нижнего уровня. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций

Означает, что наследоваться от абстрактного класса (или интерфейса) можно, а наследовать абстрактный класс от обычного нельзя (иначе можно попасть в полную задницу наследований).

Источник: 1 - 2 - 3 - 4

Оцени публикацию:
  • 10,48
Оценили человек: 10

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2019 YaPro.Ru

Главная » Веб-мастеру » PHP »