Углубленный взгляд на полиморфизм
Когда я начинал эту серию статей, я говорил о четырех столпах объектно-ориентированного программирования. Каждая из этих тем перечислены и связаны ниже.
На этом этапе я обычно хотел бы перейти к следующей теме. Однако прежде чем сделать это, я хотел бы посвятить еще один пост изучению концепции полиморфизма.
За свою карьеру я до сих пор видел лишь несколько тем, которые вызывали у тех, кто занимается объектно-ориентированным программированием, больше путаницы и проблем, чем полиморфизм. Поэтому я хотел бы обсудить это более подробно в контексте объектно-ориентированного программирования и вне какой-либо конкретной среды или приложения (например, WordPress).
В этом посте я сделаю краткий обзор того, что мы уже обсуждали, а затем вернусь к полиморфизму.
Углубленный полиморфизм
Во-первых, как уже упоминалось, я хочу быстро просмотреть то, что обсуждалось до сих пор, особенно если вы пропустили какой-либо из предыдущих постов.
Не волнуйтесь: ничто ниже не отвлекает вас от кода. Вместо этого он просто определяет термины, которые мы использовали, чтобы у вас было некоторое представление о том, что я имею в виду всякий раз, когда вы видите слово, возникающее в этой серии.
[ограничить платно = «истина»]
Абстракция
Мы абстрагируем идею чего-либо в класс. Вместо этого мы собираемся абстрагировать идеи в их классы. И здесь есть ключевая идея: класс должен представлять существительное.
Инкапсуляция
Инкапсуляция — это просто «большое» слово, которое относится к идее управления своими обязанностями (или отслеживания своих данных).
Наследование
Наследование относится к идее, что один класс, хотя и имеет собственную реализацию, буквально наследует свойства, функции и общую реализацию от родительского класса.
Полиморфизм
Полиморфизм позволяет нам ссылаться на класс одного типа, когда он может быть объявлен как другой тип.
С учетом сказанного, здесь, я думаю, все может стать немного сложнее. В предыдущих сообщениях я предоставил несколько различных примеров кода (и я призываю вас оглянуться на них).
Но в сегодняшнем посте я попытаюсь изучить эту идею немного подробнее как в объяснении, так и в коде.
Относительно наследства
Если на данный момент это не очевидно, полиморфизм тесно связан с наследованием. Подумайте об этом так: если один класс наследует свойства и методы другого класса, то он может «стоять на месте» родительского класса.
Это означает, что если у вас есть что-то вроде класса Content, а затем у вас есть два подкласса, один из которых является Post, а другой — Page, вы можете создать экземпляр класса, используя тип ссылки Content.t.
Но во время выполнения это фактически будет экземпляр типа Post. Есть смысл? Вот некоторый код в качестве примера.
Во-первых, мы начнем с определения класса Content :
<?php
class Content {
protected $title;
protected $content;
protected $metadata;
public function __construct()
{
$this->title = "Hello World!";
$this->content = "This is a sample piece of content.";
$this->metadata = "<This is the metadata of the post.>";
}
public function getTitle()
{
return $this->title;
}
public function getContent()
{
return $this->content;
}
public function getMetadata()
{
return $this->metadata;
}
}
Он имеет общие свойства, которые вы, вероятно, ожидаете: заголовок, содержание и метаданные. Конечно, эти свойства — просто строки, но в реальной ситуации они могут быть более сложными структурами данных.
Теперь давайте посмотрим на сообщение :
<?php
class Post extends Content {
private $author;
public function __construct() {
parent::__construct();
$this->author = "Tom McFarlin";
}
public function getAuthor()
{
return $this->author;
}
}
Что произойдет, если вы вызовете метод класса Post, например getTitle, который не существует, но существует в классе Content? Затем из-за наследования он будет искать метод в Post, не найдет его, а затем начнет искать его в Content.
Если он будет найден, он запустит его.
Точно так же мы можем сделать что-то подобное с классом Page и данными содержимого. Сначала мы создаем экземпляр базового класса, а затем устанавливаем свойства, специфичные для страницы. В данном случае это будет категория.
<?php
class Page extends Content {
private $category;
public function __construct() {
parent::__construct();
$this->category = "Articles";
}
public function getCategory()
{
return $this->category;
}
}
Теперь, когда мы запускаем код, мы можем начать с содержимого:
<?php
$content = new Content();
echo $content->getTitle();
Обратите внимание, что это выглядит так, как мы и ожидали, поскольку у нас есть заголовок и контент. Давайте также посмотрим на пост :
<?php
// These will work because they reside in the Content base class.
$post = new Post();
echo $post->getAuthor();
echo $post->getTitle();
Это работает, потому что у нас есть автор, но у нас также есть заголовок, потому что он находится в Content. Но если мы попытаемся вызвать getAuthor для экземпляра Post?
<?php
// These will work because they reside in the Content base class.
$post = new Post();
echo $post->getAuthor();
echo $post->getTitle();
Мы получим ошибку, потому что метод не находится в этом классе.
Итак, что нам делать? Поскольку в PHP нет сильных типов, мы не можем привести его к другому типу.
Для этого существуют шаблоны проектирования, которые я буду обсуждать в следующих постах, но PHP не позволяет это сделать так же легко, как некоторые другие языки (такие как C# или Java).
Вопросы о полиморфизме
Надеемся, приведенный выше код дает вам представление о том, как конкретный тип, такой как Post или Page, может неявно иметь свойства и методы своего базового класса Content, используемые во время выполнения.
Но это также вызывает несколько вопросов, не так ли? Например:
- Чем полезен полиморфизм? В конечном счете, это вопрос гибкости. То есть вы можете написать общий тип контента, а затем создать запись или страницу, как мы видели выше. Это дает нам все преимущества класса Content, а также дает нам, например, специфику класса Post.
- Это кажется более запутанным, чем гибким. В некотором смысле это сбивает с толку, потому что код требует небольшой трассировки. То есть вы можете начать с класса Post, а вам придется искать то, что предлагает класс Content . С другой стороны, это также позволяет очень легко ввести новый подкласс Content, а затем использовать его, когда он лучше всего подходит во время выполнения.
Что касается суперклассов и подклассов, здесь в игру вступает надежная IDE.
Конечно, всегда приятно иметь редактор, который вам нравится, но наличие такого редактора, который может интуитивно определить, что такое родительский класс, какой базовый класс и т. д., может значительно помочь в отслеживании, отладке, отслеживании и написании новых. код.
Но это содержание для другого поста, который будет после того, как мы поговорим о шаблонах проектирования.

