Вторые два столпа ООП
Как я упоминал в первом посте этой серии, вы часто будете слышать о трех столпах объектно-ориентированного программирования. Вы также можете услышать о четырех столпах объектно-ориентированного программирования.
И дело не в том, что их всего семь или что-то в этом роде. Вместо этого речь идет о том, что люди считают основополагающим для ООП: существуют ли три или четыре основных понятия?
Вы можете догадаться из предыдущей статьи (не говоря уже о названии), я считаю, что их четыре.
И в этом посте я расскажу о последних двух:
- Наследование,
- и полиморфизм
Если вы занимались каким-либо типом объектно-ориентированного программирования до прочтения этой статьи, вы, вероятно, слышали хотя бы об одном из них.
Тем не менее, давайте рассмотрим каждый из них более подробно.
Еще два столпа ООП
Прежде чем перейти к каждому из них, я хочу убедиться, что вы поняли то, что мы рассмотрели до сих пор.
Слово об анализе
Я не буду останавливаться на этом, но вся причина, по которой я сейчас говорю об основах объектно-ориентированного подхода, заключается в том, что мы переходим к другому этапу этого материала. Мы начали с этапа анализа, который включал:
Теперь к развитию
И вот мы переходим к этапу разработки . Некоторые могут назвать это основами (но я согласен, что вы не можете сделать хорошую разработку без основ, так что вот это(.
Если вы не читали предыдущий пост, я рекомендую сделать это, прежде чем продолжить, так как в нем рассматриваются концепции абстракции, инкапсуляции и их связь с WordPress.
3 Наследование
Концепцию наследования довольно легко понять. То есть один класс может наследовать атрибуты другого класса. Я приведу несколько примеров этого через мгновение, но позвольте мне дать рабочее определение для целей этого поста:
Наследование относится к идее о том, что один класс, хотя и имеет собственную реализацию, буквально наследует свойства, функции и общую реализацию от родительского класса.
Пример 1: документ
Проще говоря, предположим, что у вас есть класс с именем Document, документ имеет заголовок и содержимое. Затем есть подкласс документа, который имеет атрибуты для даты и времени. Мы могли бы назвать это PostDocument или PageDocument.
То есть PageDocument наследует свойства и атрибуты Document, а также добавляет к нему собственную реализацию. Есть смысл?
Если нет, не волнуйтесь. Сначала это не всегда «щелкает», поэтому давайте рассмотрим другой пример.
Пример 2: Сообщение
Допустим, у нас есть класс Message. Сообщение обычно имеет два свойства:
- 1 Отправитель,
- 2 Получатель.
Справедливо сказать, что существуют разные типы сообщений, верно? То есть, возможно, у нас есть EmailMessage или, может быть, у нас есть TextMessage.
У сообщения электронной почты по-прежнему есть отправитель и получатель, но их гораздо больше, верно? В нем есть такие вещи, как:
- сюжетная линия,
- необязательное приложение,
- другой набор отправителей, которым он отправлен,
- поддержка копирования других в сообщение публично или в частном порядке,
- и многое другое.
С другой стороны, TextMessage не обязательно будет иметь все вышеперечисленное. Предположим, мы говорим об обычном SMS-сообщении (а не о расширенном текстовом сообщении в чем-то вроде Hangouts, Telegram, iMessage или чем-то еще).
Этот класс будет:
- быть привязанным к номеру телефона,
- может включать группу других получателей, все из которых являются общедоступными,
- оператор связи (то есть оператор сотовой связи),
- максимальное количество символов, которые он может содержать
- возможность разбить одно сообщение на несколько сообщений, если максимальное количество символов превышает определенное количество символов.
Но это по-прежнему вызывает вопросы о свойствах и методах (или, в более общем смысле, о реализации, верно?)
Несколько слов о реализации
Когда дело доходит до объектно-ориентированного программирования, у нас есть то, что мы называем модификаторами доступа. Возможно, вы читали их в другом месте, называемом, скажем, модификаторами видимости или чем-то в этом роде.
Все то же самое.
Вкратце, эти модификаторы можно определить как:
Ключевые слова, которые контролируют, какие другие классы имеют доступ к имеющейся информации.
К счастью, эту часть легко понять:
- частные свойства и функции доступны только для класса, в котором они определены. Это означает, что PostDocument не может использовать в Document ничего, что помечено как приватное. Во всех смыслах и целях PostDocument даже не подозревает о существовании этой информации.
- защищенные свойства и функции доступны классу, в котором они определены, и любому классу-потомку. То есть любой класс, наследующий данные от базового класса или родительского класса, имеет к ним доступ. Таким образом, в отличие от частных деталей реализации, PostDocument может получить доступ к информации из Document, если он помечен как защищенный.
- публичные свойства и функции доступны всем. На самом деле это не имеет ничего общего с наследованием, а скорее с инкапсуляцией, если что. Вместо этого все дело в том, чтобы решить, к чему мы хотим, чтобы другие объекты имели доступ.
Так как же осуществляется реализация? Это зависит от языка, но PHP не поддерживает так называемое «множественное наследование». Проще говоря, данный класс в PHP может наследовать (или расширять) только один другой класс. Не несколько классов (некоторые языки поддерживают это).
Когда вы расширяете класс, подкласс наследует все общедоступные и защищенные методы родительского класса. Если класс не переопределит эти методы, они сохранят свою первоначальную функциональность.
В нашем примере мы не можем ввести другой класс, такой как WrittenDocument, который наследуется как от PageDocument, так и от PostDocument. Это либо одно, либо другое. И стоит отметить, что если он наследуется от PostDocument, он также наследует информацию от Document, потому что это подкласс подкласса класса.
4 Полиморфизм
Теперь, когда у нас есть базовое определение наследования, мы можем поговорить о полиморфизме. Хорошая новость заключается в том, что это большое и странное слово для очень простой концепции.
Плохая новость заключается в том, что мы не говорили об интерфейсах или абстрактных классах. Они грядут, но они считаются частью четырех столпов, так что не беспокойтесь о них прямо сейчас.
Вместо этого подумайте об этом так:
Полиморфизм позволяет нам ссылаться на класс одного типа, когда он может быть объявлен как другой тип.
Это все еще может сбивать с толку, но помните наш, скажем, пример с сообщением выше? Мы можем создать экземпляр класса SMSMessage, который расширяет класс Message, а затем вызвать для него определенные методы.
SMSMessage может иметь метод, который есть у класса Message. И если класс был создан как экземпляр класса SMSMessage, то он вызовет этот метод. Точно так же, если у него нет метода, но он есть у его родительского класса Message, то он вызовет этот метод.
Иногда проще всего понять это в коде, поэтому давайте сделаем это.
Во-первых, давайте определим наш класс Message :
<?php
class Message
{
public function send()
{
echo "This message is sent from the Message class.n";
}
public function receive()
{
echo "This message was received from the Message class.n";
}
}
Затем давайте определим наш класс SMSMessage. Обратите внимание, что у него нет функции receive(). Это будет важно на мгновение:
<?php
class SMSMessage extends Message
{
public function send()
{
echo "This message is sent from the SMSMessage class.n";
}
}
Теперь давайте создадим экземпляр нашего класса Message и вызовем несколько методов:
<?php
$message = new Message();
$message->send();
$message->receive();
И давайте сделаем то же самое, используя класс SMSMessage:
<?php
$message = new SMSMessage();
$message->send();
$message->receive();
Если вам нужен весь скрипт, вы можете увидеть его здесь, скачать и выполнить локально.
Наследование, полиморфизм и WordPress
Вот вывод (и мы рассмотрим это подробнее, когда перейдем к интерфейсам и абстрактным классам): когда класс расширяет другой класс и у него нет деталей реализации, которые есть у его родительского класса, будет использоваться реализация родителя.
Другой способ думать об этом — «выработать цепочку подчинения». Он начнется с самого низкого класса по сравнению с тем, что мы создали. В нашем примере выше это SMSMessage. Если он не найдет его там, он переместится в класс, который он расширяет. (И если он не найдет его там, и этот класс расширяет класс, он попытается там.)
Вся полиморфность заключается в следующем: мы создали экземпляр класса одного типа, SMSMessage, но он использует реализацию класса другого типа (который он наследует, да, но это, тем не менее, другое).
Написание классов на WordPress
Наконец, я хотел бы оставить вас с этим: я упоминал что-то подобное в предыдущем посте, но я хочу повторить это здесь.
Независимо от того, сколько из этих концепций использует ядро WordPress, это не имеет значения, потому что мы можем писать высококачественный объектно-ориентированный код на WordPress, который взаимодействует с WordPress и прекрасно работает с WordPress (и другим сторонним кодом — не всегда)., но многократно).
Что дальше?
Далее мы рассмотрим интерфейсы и абстракции.
Они по-прежнему являются фундаментальными для объектно-ориентированного программирования, но если вы поняли два предыдущих поста, вы готовы к прочному опыту работы с будущими концепциями.
А если нет, не волнуйтесь! Вы всегда можете обсудить это в комментариях или мы можем поговорить об этом по электронной почте.