Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5 для начинающих

  Все выпуски  

От скаляров к объектам


Вниманию читателей!

Отдельные выпуски рассылки в той или иной мере взаимосвязаны. С предыдущими выпусками Вы можете ознакомиться:

  1. в архиве рассылки (оригиналы выпусков);
  2. на сайте рассылки (исправленные и дополненные версии).

# # #

Вы также можете подписаться на рассылку "PHP 5: Новые возможности".

PHP 5 для начинающих

На текущем практическом занятии будут рассмотрены конкретные примеры описания средствами PHP точек и отрезков на числовой оси и на плоскости при помощи различных типов данных; обращено внимание на недостатки и преимущества различных способов представления данных.

Рассмотрим одномерную числовую ось с нанесенными на нее произвольными точками (Рисунок 6.1, «Числовая ось с нанесенными точками»). Как видно, любая точка на этой оси может быть однозначно задана числовой координатой. Что касается отмеченных точек, то координаты некоторых из них являются целыми числами, а некоторых - числами с плавающей запятой. Отобразим это с помощью PHP кода.

<?php

$x = -8;
$y = 4;
$z = 12;

$m = -16.7;
$n = -1.8;

?>
        
var_dump($x);
int(-8)
var_dump($m);
float(-16.7)

Таким образом, каждой переменной соответствует точка на числовой оси.


Усложним задачу и попытаемся отобразить с помощью скалярных переменных уже не отдельные точки, а целый отрезок (Рисунок 6.2, «Числовая ось с нанесенным отрезком»). Для этого придется задать координаты двух его точек - начала и конца.

<?php

// Segment X
$x0 = -2;
$x1 = 5;

?>
        

С задачей мы справились, но вот необходимость хранить параметры одного и того же отрезка в двух разных переменных представляется не самым лучшим решением. Что, если вместо отрезка, для однозначного задания которого достаточно определить всего два значения, придется моделировать что-то более сложное, с десятками параметров? Что, если вместо одного объекта их будет множество?


Ограниченность скалярных типов данных помогают преодолеть составные типы - массивы и объекты.

Использование массивов позволяет собрать «под одной крышей» все параметры, относящиеся к моделируемому предмету или явлению (в нашем случае, отрезку - см. Рисунок 6.2, «Числовая ось с нанесенным отрезком»).

<?php

// Segment X
$x = array('x0' => '-2',
           'x1' => '5');

?>
        

Или, с учетом небольшого количества параметров, еще проще.

$x = array(-2, 5);  // Segment X

Далее перейдем к двумерной плоскости (Рисунок 6.3, «Плоскость с точками и отрезком»). Для однозначного определения каждой точки теперь потребуется определять уже две координаты, а для отрезка - четыре.

<?php

$a = array(-10, 5);
$b = array(3, 12);
$c = array(5, -10);

$d = array(2, -3);
$e = array(16, 4);

$de = array($d, $e);

?>
        

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


Если проинспектировать, например, переменные $x и $a, то особой разницы между ними мы не заметим; а ведь эти переменные отображают совершенно разные сущности: отрезок на числовой оси и точку на двумерной плоскости.

var_dump($x);
array(2) {
  [0]=>
  int(-2)
  [1]=>
  int(5)
}
        
var_dump($a);
array(2) {
  [0]=>
  int(-10)
  [1]=>
  int(5)
}
        

Конечно, можно снова вернуться к ассоциативным массивам и использовать для разных сущностей разные ключи (например, x0 и x1 для отрезка и x и y для точки). Однако, в уже упоминавшемся случае с множеством сущностей, для описания каждой из которых необходимо множество параметров, распознавание таких массивов окажется весьма затруднительным.

Кроме того, любое приложение предполагает не только описание данных, но и какую-то их обработку. Например, точка на плоскости может быть сдвинута относительно своего первоначального положения (Рисунок 6.4, «Сдвиг точки на плоскости»). Для этого придется разработать специальную функцию.

<?php

function move($p, $dx, $dy)
{
    $x = $p[0] + $dx;
    $y = $p[1] + $dy;

    return array($x, $y);
}

$p1 = array(-6, -5);
$p2 = move($p1, 11, 11);

var_dump($p2);

?>
        
array(2) {
  [0]=>
  int(5)
  [1]=>
  int(6)
}
        

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

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

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

Таблица 6.1. Сущности, их свойства и представления
Сущность Свойства Переменные Ссылка
Точка на числовой оси Координата относительно числовой оси $x, $y, $z (integers); $m, $n (floats) Рисунок 6.1, «Числовая ось с нанесенными точками»
Отрезок на числовой оси Начальная и конечная точки $x (array) Рисунок 6.2, «Числовая ось с нанесенным отрезком»
Точка на плоскости Координаты относительно двух числовых осей $a, $b, $c, $d, $e (arrays) Рисунок 6.3, «Плоскость с точками и отрезком»
Отрезок на плоскости Начальная и конечная точки $de (array) Рисунок 6.3, «Плоскость с точками и отрезком»

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

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

Тем самым напрашивается предложение создать для каждой сущности средствами самого языка программирования какое-то обобщенное описание, своего рода шаблон. В терминологии объектно-ориентированного программирования такой шаблон называется классом, а конкретные представления данной сущности, ее воплощения, основанные на созданном шаблоне, - объектами. Например, в нашем случае (конечно, после соответствующего преобразования кода) можно было бы говорить о классе Точка на плоскости, представленном объектами $a, $b, $c и др.; о классе Отрезок на плоскости, представленном объектом $de; и т. д.

В заключение рассмотрим, как мог бы выглядеть один из таких классов (Пример 6.1, «Класс Point»), а также создадим объект, представляющий этот класс (Пример 6.2, «Создание объекта класса Point»).

Пример 6.1. Класс Point

<?php

class Point { 1
    public $x; 23
    public $y; 4

    function __construct($x, $y) 5
    {
        $this->x = $x; 6
        $this->y = $y; 7
    }

    public function move($dx, $dy) 8
    {
        $this->x += $dx; 9
        $this->y += $dy; 10
    }
}

?>
            
1

Объявление класса Point.

2

Модификатор доступа public определяет максимально возможную видимость - не только из контекста самого класса, но и из глобального контекста.

3

Координата по оси абсцисс.

4

Координата по оси ординат.

5

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

6

Установка свойства $x (координата по оси абсцисс). Специальная переменная $this обозначает непосредственно тот объект, в контексте которого она используется.

7

Установка свойства $y (координата по оси ординат).

8

Объявление публичной (доступной из глобального контекста) функции для сдвига точки. Функция принимает значения сдвига по оси абсцисс и по оси ординат.

9

Сдвиг по оси абсцисс на заданную величину.

10

Сдвиг по оси ординат на заданную величину.


Пример 6.2. Создание объекта класса Point

<?php

$p = new Point(-6, -5); 1
$p->move(11, 11); 2

var_dump($p); 3

?>
            
1

Создаем новый объект класса Point с начальными координатами (-6, -5).

2

Производим сдвиг объекта на 11 позиций вправо и на 11 позиций вверх.

3

Инспектируем текущее состояние объекта.

object(Point)#1 (2) { 1
  ["x"]=>
  int(5)
  ["y"]=>
  int(6)
}
            
1

Объект принадлежит классу Point.


Created with DocBook


В избранное