vasiljevalentin

Привет! Меня зовут Валентин. Говорят, чтобы разобраться в чем-то достаточно хорошо, нужно попробовать объяснить это другому. Поэтому я решил написать несколько постов о программировании и заодно узнать / понять какие-то важные штуки получше. Если вдруг вы захотите больше контента, а так же послушать мой ужасный английский, вот ссылка: https://www.youtube.com/@VasilevValentin
Пикабушник
поставил 4 плюса и 0 минусов
Награды:
5 лет на Пикабу
177 рейтинг 69 подписчиков 12 подписок 3 поста 1 в горячем

Полиморфизм

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

Полиморфизм Опрос, Программирование, Oop, Ооп, IT, Длиннопост

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 и общую безграмотность. Отдельное спасибо всем, кто заходит и подписывается на ютуб канал. Я начинаю готовить видео на тему ООП. Может быть примеры кода на видео будут более понятны.

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

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

Что рассмотрим в следующий раз?
Всего голосов:
Показать полностью 1 1

Инкапсуляция и Наследование

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


Инкапсуляция и Наследование Опрос, PHP, Программирование, Ооп, Oop, Длиннопост

Примеры все еще на PHP

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

Как совершенно справедливо заметили в комментах, я не смог объяснить что такое ооп в первом посте. Ну это и не мудрено. Попробую приоткрыть пользу этого подхода опять.

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

<?php

class Text {

private $text;

public function __construct($text){

$this->text = $text;

}

public function printText() {

echo $this->text;

}

}

$hello = new Text("Hello, "); // создаем объект hello

$world = new Text("World!"); // создаем объект world

$hello->printText(); // вызываем метод print объекта hello

$world->printText(); // вызываем метод print объекта world

echo PHP_EOL.get_class($hello); // проверяем класс

echo PHP_EOL.get_class($world); // проверяем класс

?>

Здесь я добавил конструктор класса. С его помощью я передаю параметр с текстом. Этот параметр записывается в свойство text. Перед объявлением свойства text я использовал ключевое слово private, которое запрещает доступ к свойству извне класса. Функция get_class возвращает имя класса. Здесь я проверю, что класс двух объектов совпадает, почему это важно? Узнаем в следующих постах.

Определение возможности доступа к свойствам и методам класса (public, private, protected) - это сокрытие.

Таким образом получилось, что класс Text работает с параметром, который я передал через конструктор и методами, которые я описал в классе. Такое объединение данных и методов работы с ними + сокрытие - это инкапсуляция.

Наследование

Итак, у нас есть класс, который принимает параметр и печатает текст. В нашем проекте нужно печатать текст в двух стилях. Заголовки, которые будут написаны капсом и обычные строки, у которых только первая буква будет большой. Мы можем написать функции для каждого случая обработки строк. Можем написать разные классы. Или можем использовать уже готовый класс и расширить его возможности. Напишу еще пару классов.

<?php

class Text {

protected $text;

public function __construct($text){

$this->text = $text;

}

public function printText() {

return $this->text;

}

}

class Header extends Text {

public function printText() {

return strtoupper($this->text);

}

}

class Sentence extends Text {

public function printText() {

return ucfirst(strtolower($this->text));

}

}

$header = new Header("hello, world!");

$sentence = new Sentence("hello, WORLD!");

echo $header->printText();

echo PHP_EOL;

echo $sentence->printText();

?>

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

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

Вместо заключения. Я, конечно, не ожидал такого отклика на первую статью. Тем более удивительно, что рейтинг на аккаунте стал немного больше, а не наоборот. Значит, все не зря. Более того, 63 человека стали подписчиками. Это уже совсем удивительно, ведь судя по комментариям, про ооп все уже все знают. Наверное, вы подписались из-за искрометных мемчиков вначале постов. В общем, всем спасибо! И отдельное спасибо новым подписчикам на ютубе :)

Что рассмотрим в следующий раз?
Всего голосов:
Показать полностью 1

Поговорим про ооп1

Говорят, чтобы разобраться в чем-то достаточно хорошо, нужно попробовать объяснить это другому. Поэтому я решил написать несколько постов о программировании и заодно узнать / понять какие-то важные штуки получше. В этой первой статье начнем говорить об объектно-ориентированном подходе в программировании. Примеры я буду писать на языке PHP. Но, надеюсь, общие концепции будут применимы для любого языка.


Поговорим про ооп PHP, Программирование, Ооп, Oop, Длиннопост

Мем из интернетов

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

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

Еще позднее функций стало недостаточно и программисты придумали классы и объекты.
Класс - часть программы, которая может содержать внутри функции и переменные, оформленная для многократного использования в более сложных конструкциях.
Предположим, мы хотим создать программу, которая выведет строку "Hello, world!" несколько раз.
На PHP это будет выглядеть, например так:

Здесь три команды вывода текста на экран. Поэтому удобно использовать функцию:

<?php
echo 'Hello, world!';
echo 'Hello, world!';
echo 'Hello, world!';
?>

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

<?php
function hello(){
echo 'Hello, world!';
}
hello();
hello();
hello();
?>

Что на счет ООП?

Создадим класс Текст. Он будет печатать текст и хранить этот текст внутри себя.

<?php
class Text{
public $text = 'Hello, world!';
function printText()
{
echo $this->text;
}
}
$hello = new Text();
$hello->printText();
?>

Здесь у нас класс Текст. У него есть общедоступное свойство текст, которое равно "Hello, world" и метод, который выводит этот текст на экран. Из такого простого примера не очень понятна выгода классов по отношению к простым функциям. Однако такой класс имеет рад преимуществ.

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

Во-вторых, объекты такого класса можно создать несколько раз. И использовать в разных частях программы. Объекты эти будут одинаковыми, но они смогут обладать разными свойствами.

В-третьих, наследование, полиморфизм и паттерны программирования. Здесь скрыта магия ооп. Но раскрыть ее в одной статье будет, пожалуй, невозможно.

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

В будущих статьях я попробую описать все основные моменты работы с ооп. Попробую разобраться в ни сам и объяснить заинтересованным. Так что, присоединяйтесь.

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

Показать полностью 1
Отличная работа, все прочитано!