В предыдущей статье мы представили концепцию объектно-ориентированного наследования, попытались поместить его в термины непрофессионалов, а затем также взглянули на концептуальную модель его работы в контексте программирования.
Но прежде чем мы пойдем дальше и / или если вы просто присоединяетесь к серии, просмотрите все, что мы уже рассмотрели, прочитав предыдущие статьи:
- Введение
- Классы
- Типы
- Управляющие структуры: условные высказывания
- Управляющие структуры: петли
- Функции и атрибуты
- Сфера
- Сборка плагина I
- Сборка плагина II
- Документ Плагин I
- Документ Плагин II
- Наследование я
Да, мы многое рассмотрели, но для того, чтобы заложить основу для начинающего, чтобы иметь сильное место, с которого можно начинать писать объектно-ориентированный PHP, нужно многое изучить.
С учетом сказанного, наследование — это то, с чего мы начинаем переходить к промежуточным темам парадигмы, так что это будет заключительная статья, в которой будет дан обзор концепций новичка, после чего мы закончим серию кратким сообщением.
Наследование пересмотрено
Напомним, что мы определили наследование следующим образом:
Наследование — это когда один класс служит родительским классом для дочернего класса, который предоставляет ряд атрибутов и методов, общих как для родительского, так и для дочернего; Однако ребенок как умение вводит свои атрибуты.
Это немного менее формально, чем то, что вы можете найти в академической книге или даже в Википедии, но оно все же объясняет идею в терминах, которые иллюстрируют эту мысль.
В этой статье мы рассмотрим весь необходимый код, функции и зарезервированные слова, относящиеся к теме, мы рассмотрим, как мы можем реализовать его в PHP очень, очень простым, независимым от платформы способом. , а затем мы рассмотрим фактическую реализацию наследования в WordPress.
Так что с этим набором в качестве нашей дорожной карты для статьи, давайте продолжим и начнем.
PHP объекты
Чтобы реализовать наследование в объектно-ориентированном PHP, существует ряд зарезервированных слов, с которыми нам необходимо ознакомиться. К счастью, большинство слов, которые мы уже охватили, и те слова, которых у нас нет, достаточно ясны, чтобы их было легко запомнить.
Поэтому, прежде чем мы углубимся в изучение кода, давайте взглянем на все зарезервированные слова в языке, который нам нужно знать, чтобы мы могли реально приступить к созданию чего-либо.
-
extends
— зарезервированное слово, которое указывает, что один класс является дочерним для другого класса. Например, в нашей предыдущей статьеPost
расширяетContent
. Мы скоро увидим это в игре. -
private
— это атрибут, который применяется к свойствам и функциям, которые означают, что они доступны только в контексте класса, в котором они определены. -
protected
аналогиченprivate
за исключением того, что свойства и методы, помеченные как таковые, доступны для данного класса и любых дочерних классов. -
public
является противоположностьюprivate
в том смысле, что он означает, что любой класс — данный класс, подкласс или сторонний класс — может получить доступ к свойству или методу, чтобы изменить его информацию или вызвать функцию.
Вы также должны быть знакомы с оператором ::
, но мы рассмотрим это чуть позже в статье, когда начнем рассматривать код.
И это все — ничего страшного, правда? И что еще лучше, если вы следили за нами на протяжении всей этой серии, то, вероятно, вы знакомы с каждым словом, за исключением extends
.
В любом случае, с учетом сказанного, давайте начнем работать над примером.
Пример кода
Чтобы начать писать пример кода, нам нужно точно указать, что именно мы будем пытаться моделировать (в конце концов, именно это и делает код, не так ли?).
В соответствии с темой, используемой в этой серии, особенно в предыдущей статье, у нас будет родительский класс Content
и два дочерних класса, каждый из которых будет называться Comment
и Post
соответственно.
Это позволит нам увидеть, как свойства и методы существуют в одном классе, и как дети могут получить доступ к атрибутам своих родителей, а также как родители могут защитить свои свойства и функции от своих детей.
Но реализация продемонстрирует гораздо больше, чем просто разговор об этом, поэтому давайте начнем писать код.
Родительский класс
В нашем примере родительским классом будет Content
поскольку оба подкласса, то есть Post
и Comment
являются типами контента, с которым связана уникальная информация, которая не относится к классу Content
.
Ключ к наследованию состоит в том, чтобы идентифицировать все свойства и методы, которые являются общими для всех классов, и сохранять их определенными в родительском классе или, в нашем классе, в Content
.
Хотя это может варьироваться в зависимости от того, как вы это просматриваете, мы настроим Content
, чтобы он включал:
- дата, когда контент был опубликован
- Автор
- метод для сохранения контента
- метод для форматирования контента
- метод для извлечения контента
- и способ поиска автора контента
Сначала мы рассмотрим код, затем объясним все, что с ним происходит.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<?php
class Content {
protected $publish_date;
protected $author;
private $content;
public function __construct() {
date_default_timezone_set( ‘GMT’ );
$date = new DateTime();
$this->publish_date = $date->format( ‘Ymd H:i:s’ );
$this->author = »;
}
public function save( $author, $content ) {
$this->author = $author;
$this->content = $this->format_content( $content );
$this->content;
}
public function read() {
return $this->content;
}
private function format_content( $content ) {
return strip_tags( stripslashes( $content ) );
}
public function get_author() {
return $this->author;
}
}
|
Как упоминалось ранее, у нас есть два protected
атрибута и private
атрибут. Напомним, что это означает, что все подклассы могут обращаться к $publish_date
и $author
, но только Content
может обращаться к атрибуту $content
.
Также обратите внимание, что большая часть кода, который вы видите в вышеприведенном классе, является базовым объектно-ориентированным PHP. Нет ничего особенного, что напрямую связано с наследованием, кроме некоторых модификаторов доступа, которые мы объявили. То есть это довольно распространенный код, который мы видели в этом руководстве.
Одна из вещей, которую стоит отметить, заключается в том, что частная функция используется для демонстрации двух вещей:
- Как
private
функции доступны только в контексте класса, в котором они определены. - Удаляет любые теги и косые черты из содержимого, чтобы разметка не могла быть сохранена вместе с содержимым.
Конечно, этот код не связан ни с базой данных, ни с файловой системой, ни с чем-либо, но суть все еще остается.
Обратите внимание, что в приведенном выше коде есть несколько вещей, которые нам нужно было добавить, чтобы удовлетворить требования PHP. Они выходят за рамки этой статьи, но здесь стоит указать:
- Код
date_default_time_set
необходим для установки часового пояса, из которого можно получить время. - Конструктор отвечает за первоначальную установку даты публикации контента и инициализирует свойство author пустой строкой. Это связано с тем, что у
Post
может быть свой автор, а уComment
и собственный автор. Как мы увидим позже,Comment
может даже переопределить дату публикации по умолчанию.
Также обратите внимание, что мы можем извлечь контент из метода read
и мы можем получить автора из функции get_author
.
Первый ребенок
Далее, давайте продолжим и создадим подкласс Post
. Сначала мы посмотрим на код, а затем посмотрим, как он взаимодействует с только что созданным классом Content
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<?php
class Post extends Content {
public function __construct() {
parent::__construct();
$this->author = ‘Tom McFarlin’;
}
public function post( $content ) {
$this->format_content( $content );
}
}
|
Класс кажется маленьким, верно? Нет никаких свойств — потому что он наследует их от класса Content
— и есть только две функции, одна из которых уникальна для класса — post
.
Обратите внимание, что в конструкторе мы сначала вызываем родительский конструктор, используя оператор ::
. Вы можете прочитать об этом намного больше в руководстве , но достаточно сказать, что оператор зарезервирован для ссылки на ряд различий вне класса, в котором он определен. В нашем случае это вызов конструктора родителя.
Далее я решил указать свое имя как автора поста. Обратите внимание, что я использую ключевое слово $this
. Поскольку подкласс наследует свойства от своего родителя, он может ссылаться на эти свойства и, если они были определены внутри себя.
Обратите внимание, что это возможно не только потому, что Post extends Content
но и потому, что свойство также помечено как protected
в Content
. Если бы он был помечен как private
, это было бы невозможно.
Второй ребенок
Теперь, когда мы создали класс Post
, у нас также есть класс Comment
который, напомним, представляет кого-то, оставляющего комментарий к сообщению. Если бы это был код производственного уровня, было бы гораздо больше кода: нам нужно было бы связать комментарий с сообщением, определить, является ли комментарий ответом на существующий комментарий, отметить состояние комментария и т. Д.
Но в целях демонстрации наследования мы упускаем все это и концентрируемся только на тех вещах, которые могут управлять концепциями.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?php
class Comment extends Content {
public function __construct() {
parent::__construct();
}
public function add( $comment ) {
$this->save( ‘John Doe’, $comment );
}
}
|
Как видите, код Comment
мало чем отличается от Post
кода. В некоторой степени — это хорошо, потому что это показывает, что мы абстрагировали нужные части в наш базовый класс.
В любом случае, обратите внимание, что после того, как мы создадим Comment
, мы сделаем наш вызов родительского конструктора. Далее мы определяем метод add
который отвечает за принятие входящего комментария и его сохранение, передавая автора комментария и его содержимое в метод save
.
Приятно то, что метод save
уже определен в базовом классе, который также обрабатывает все форматирование с помощью private
функции, поэтому мы получаем эту функциональность при создании дочернего класса.
Работа с примером
Сделав это, давайте запустим пару примеров, чтобы показать, как кусочки сочетаются друг с другом. Чтобы этот код выполнялся, все, что вам нужно, — это веб-сервер, каталог, из которого можно запускать сценарии PHP, и текстовый редактор.
Сначала мы создадим экземпляр Content
а затем вызовем оператор отладки, чтобы увидеть, что составляет экземпляр класса.
1
2
|
$content = new Content();
var_dump( $content );
|
Разрешив все работает правильно, вы должны увидеть все, что выше.
Далее, давайте продолжим и создадим пост. Поскольку мы устанавливаем всю информацию в контексте класса, все, что нам действительно нужно сделать, — это вызвать функцию класса, чтобы отобразить информацию.
Например:
1
2
|
$post = new Post();
echo ‘The post author is: ‘ .
|
Опять же, поскольку мы настроили все в самом коде, простой вызов метода демонстрирует концепцию.
Наконец, мы можем создать Comment
, вызвать метод add
для экземпляра класса, попытаться передать вредоносный код (только для того, чтобы наш код был удален). Если все идет хорошо, вы должны увидеть следующее:
1
2
3
|
$comment = new Comment();
$comment->add( ‘<script type=»text/javascript»>alert(«This is my comment.»);</script>’ );
echo ‘The comment reads: ‘ .
|
И это все: наша простая демонстрация наследования.
Наследование в WordPress
Когда дело доходит до рассмотрения наследования в WordPress, самое первое, что приходит мне в голову — и, вероятно, другим разработчикам, — это API виджетов . Причина, по которой я это говорю, заключается в том, что API основан на наследовании.
Конечно, виджеты могут быть созданы без использования API, но я бы сказал, что это ошибка в разработке. Зачем усложнять себе жизнь, если для этого уже есть основа? Но я отвлекся.
Приятной особенностью этого конкретного API является то, что он демонстрирует все основные моменты объектно-ориентированного программирования и наследования на работе. Например, вот пример кода, взятого непосредственно из Кодекса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<?php
class My_Widget extends WP_Widget {
/**
* Sets up the widgets name etc
*/
public function __construct() {
// widget actual processes
}
/**
* Outputs the content of the widget
*
* @param array $args
* @param array $instance
*/
public function widget( $args, $instance ) {
// outputs the content of the widget
}
/**
* Outputs the options form on admin
*
* @param array $instance The widget options
*/
public function form( $instance ) {
// outputs the options form on admin
}
/**
* Processing widget options on save
*
* @param array $new_instance The new options
* @param array $old_instance The previous options
*/
public function update( $new_instance, $old_instance ) {
// processes widget options to be saved
}
}
|
Теперь, когда мы рассмотрели концептуальную модель, посмотрели на ключевые слова и методологию, написали наш собственный код и создали наш собственный пример, следовать ему будет относительно легко.
Но вот в чем дело: один из лучших способов улучшить код при написании любого типа кода — постоянно практиковать концепции. То есть исследовать идеи, написанные другими людьми, которые сделали более продвинутые вещи, чем вы в предыдущей работе.
В качестве примера рассмотрим первый пример, представленный в Кодексе WordPress. И если вы работаете с более поздней версией PHP, которая поддерживает такие функции, как пространства имен (немного более сложная тема), то посмотрите также и второй пример .
Чем больше вы просматриваете код и дразните его, тем больше вы узнаете о нем. Но если мы пойдем дальше, чем в этой статье, мы выйдем за рамки всей серии.
К концу
К этому моменту мы рассмотрели весь материал для начинающих, необходимый для того, чтобы заложить основу для руководства для начинающих по написанию объектно-ориентированного PHP. В заключительной статье мы предоставим краткое изложение всего, что мы рассмотрели, чтобы у нас была единственная ссылка на большие идеи, которые можно добавить в закладки, сохранить или использовать позже.
Кроме того, у нас будет небольшой период обсуждения последующих серий, но мы сохраним это до тех пор.
На данный момент, если у вас есть какие-либо вопросы, комментарии и / или отзывы о содержании, коде или примерах выше, не стесняйтесь делать это в разделе комментариев ниже.