4

Полиморфизм

Серия ООП

Сначала определение из википедии - способность функции обрабатывать данные разных типов.

1 + '1' и другие приколы

1 + '1' и другие приколы

PHP - язык с динамической и слабой типизацией, это значит, что в процессе работы программы тип переменной может быть изменен. Более того, операнды не обязаны быть одного типа и интерпретатор сможет обработать такие варианты операций без ошибок:

<?php

echo 1 . 1; // 11

echo PHP_EOL;

echo 1 + 1; // 2

echo PHP_EOL;

echo 1 + '1'; // 2

?>

Такое поведение уже формально подпадает под определение, но мы конечно хотим от полиморфизма совсем другого.

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

Например, у нас есть новостной сайт. И мы получаем из базы данных информацию о новостях, чтобы вывести их пользователю. Чтобы не подключать бд к php песочнице, определим формат новости как json объект:

{

"title": "This is title",

"text": "This is text",

"time": "2024-01-13 12:00:00"

}

Напишем функцию, которая разберет этот json на отдельные поля и выведет на экран с нужным форматированием.

<?php

$jsonString = '{"title": "This is title", "text": "This is text", "time": "2024-01-13 12:00:00"}';

function publish($jsonString){

$jsonObject = json_decode($jsonString);

echo "<h1>$jsonObject->title</h1>";

echo PHP_EOL;

echo "<p>$jsonObject->text</p>";

echo PHP_EOL;

echo "<span>$jsonObject->time</span>";

}

publish($jsonString);

?>

Пока что неплохо справляемся и без ооп с полиморфизмом. Давайте добавим на наш сайт не только новости, но еще и статьи. В статьях не будет времени публикации, но будет имя автора. К сожалению, наша функция перестанет работать, если мы передадим такой json в нее. И тогда надо писать другую. И так для каждого типа контента. Конечно можно добавить несколько if - else и перерисовать дизайн блоков в зависимости от типов, но есть способ получше.

Теперь нам придется написать несколько классов.

<?php

class News

{

private $jsonString;

public function __construct()

{

$this->jsonString = '{"title": "This is title", "text": "This is text", "time": "2024-01-13 12:00:00"}';

}

public function publish()

{

$jsonObject = json_decode($this->jsonString);

echo "<div class='news'>";

echo "<h1>$jsonObject->title</h1>";

echo "<p>$jsonObject->text</p>";

echo "<span>$jsonObject->time</span>";

echo "</div>";

}

}

class Article

{

private $jsonString;

public function __construct()

{

$this->jsonString = '{"title": "This is title", "text": "This is text", "author": "Pikabu Member"}';

}

public function publish()

{

$jsonObject = json_decode($this->jsonString);

echo "<div class='article'>";

echo "<h2>$jsonObject->title</h2>";

echo "<p>$jsonObject->text</p>";

echo "<span>$jsonObject->author</span>";

echo "</div>";

}

}

$contents[] = new News();

$contents[] = new Article();

foreach($contents as $content){

$content->publish();

echo PHP_EOL."<div class='divider'></div>".PHP_EOL;

}

?>

Классы News и Article имеют одно приватное свойство jsonString. Заполняют его при создании объекта в конструкторе и выводят информацию из этого свойства в методе publish.

Таким образом мы можем использовать один метод для отрисовки данных из разных классов. И в главном потоке программы использовать простую конструкцию foreach(){$content->publish} для вывода разных отформатированных блоков.

Кто-то также говорит, что многие реализации должны принадлежать одному интерфейсу. То есть, мы должны определить общий интерфейс для классов его реализующих. На этапе вызова общего метода проверить принадлежность к интерфейсу. Таким образом мы сможем расширять программу многими классами и не задумываться об изменении главной программы.

<?php

interface IContent

{

function publish();

}

class News implements IContent

{

private $jsonString;

public function __construct()

{

$this->jsonString = '{"title": "This is title", "text": "This is text", "time": "2024-01-13 12:00:00"}';

}

public function publish()

{

$jsonObject = json_decode($this->jsonString);

echo "<div class='news'>";

echo "<h1>$jsonObject->title</h1>";

echo "<p>$jsonObject->text</p>";

echo "<span>$jsonObject->time</span>";

echo "</div>";

}

}

class Article implements IContent

{

private $jsonString;

public function __construct()

{

$this->jsonString = '{"title": "This is title", "text": "This is text", "author": "Pikabu Member"}';

}

public function publish()

{

$jsonObject = json_decode($this->jsonString);

echo "<div class='article'>";

echo "<h2>$jsonObject->title</h2>";

echo "<p>$jsonObject->text</p>";

echo "<span>$jsonObject->author</span>";

echo "</div>";

}

}

$contents[] = new News();

$contents[] = new Article();

foreach($contents as $content){

if ($content instanceof IContent) {

$content->publish();

echo PHP_EOL."<div class='divider'></div>".PHP_EOL;

}

}

?>

Вместо заключения. Хоть праздники уже закончились, но статью я дописал только сейчас, поэтому - Желаю всем счастливого нового года, денег, тепла и мира.

Спасибо всем, кто смог дочитать этот пост до конца несмотря на ужасное оформление, примеры на php и общую безграмотность. Отдельное спасибо всем, кто заходит и подписывается на ютуб канал. Я начинаю готовить видео на тему ООП. Может быть примеры кода на видео будут более понятны.

Ссылки на полезные документы:

Ну и в конце добавлю опрос

Что рассмотрим в следующий раз?
Всего голосов:

Лига программистов

2.1K поста11.9K подписчиков

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества