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

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

Честно говоря, проще всего эти понятия расписаны тут, но если Вам этого мало, то читайте ниже.

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

Язык PHP поддерживает полиморфизм в том смысле, что позволяет использовать вместо экземпляров родительского класса экземпляры подкласса. Дело в том, что в каждом классе может присутствовать только один метод с определенным именем. Пример:

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

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

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

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


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

youtube.com/watch?v=7hFivbgIEqk

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

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