http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

PHP и WEB для новичков (часть 7)

 

Классы

 
Автор: Владислав Демьянишин
 
PHP и WEB для новичковУже пройдено достаточно материала для написания больших и сложных скриптов. Однако остается еще кое-что из технологий программирования, позволяющих несколько упростить реализацию сложных систем. Одна из этих технологий - так называемое объектно-ориентированное программирование (ООП).
 
Мы не станем рассматривать саму концепцию ООП, потому что это несколько выходит за рамки данного курса. Я попробую рассказать эту концепцию упрощенно и достаточно для работы.
ООП является попыткой воплотить в программном коде объекты реального мира, реальные связи и взаимодействие между ними. Объекты являют собой отображение реальных объектов, а их внутренняя организация закрыта от доступа другими объектами.
Допустим, перед нами стоит задача написания интернет-магазина. Сначала определяем для себя предметную область, с которой будем работать. Это такие вещи, как покупатели, товары, заказы, корзины с покупками. Каждый из этих объектов имеет свои свойства и набор операций (методов) над этими свойствами.
 
Например, покупатель - это конкретный человек с именем, некоторым логином и паролем для входа в систему, счет (баланс) и т.п. Покупатель может выполнять такие операции, как вход/выход из системы, операции с покупками и заказами и т.д.
Реального покупателя, как и товары, заказы представляем в системе в виде объектов, а потом эти объекты взаимодействуют между собой посредством вызова методов друг друга.
 
Каждый покупатель является объектом, а все покупатели принадлежат к некоему классу "покупатель". Класс определяет свойства и методы объекта.
Разумеется, это может показаться не до конца понятным для человека, впервые имеющим с этим дело, но я надеюсь, что после нескольких примеров все станет на свои места. Объявим класс покупателя (скрипт customer.inc.php):
 
<?
class Customer {
 var $fio;
 var $login;
 var $password;
 var $balance;
 
 function Customer($login, $fio) {
  $this->login = $login;
  $this->fio = $fio;
  $this->password = "";
  $this->balance = 0;
 }
 
 function getBalance() { return $this->balance; }
} // end of class
?>
 
Тут мы описали класс Customer, который представляет все объекты покупателей. После ключевого слова class и имени класса Customer указываем свойства (поля) класса - внутренние переменные объекта (в данном случае - имя покупателя $fio, логин $login и т.д.).
 
В большинстве случаев эти переменные должны использоваться только объектом класса и не должны использоваться напрямую извне класса (этот принцип называется инкапсуляцией).
После указания полей объявляем функции (методы) класса. В данном случае это функция Customer и функция getBalance(), возвращающая баланс покупателя. Поля и методы еще называют членами класса.
Следует заметить, что класс - это только декларация, а реально образованные от него экземпляры и называются объектами. Именно к объектам можно обращаться из кода скрипта, поскольку именно они обладают выделенной памятью для хранения данных.
 
Функция, названная одноименно с классом (в данном случае - Customer()), называется конструктором. Она вызывается каждый раз, когда необходимо создать новый экземпляр (объект) данного класса.
Обратите внимание, как выглядит внутри класса обращение к полям - это конструкция $this->имя_поля. Новый объект (как было сказано ранее, его еще называют экземпляром класса) создается при помощи оператора new:
 
<?
require_once "customer.inc.php";
$customer = new Customer("mylogin", "Вася Пупкин");
 
$balance = $customer->getBalance();
echo "баланс покупателя: $balance<br />";
echo "имя покупателя: $customer->fio";
?>
 
Обратите внимание, как вызываются методы объекта - аналогично через "->". Доступ к полям объекта осуществляется так же, причем перед именем поля знак $ (доллар) не ставится.
Другим очень важным свойством классов является способность к наследованию. Для каждого класса можно объявить класс-потомок, который будет иметь тот же самый набор полей и методов, но может иметь дополнительные поля и методы, а также переопределять некоторые методы.
 
Наследование применяют при проектировании сложных систем, в которых конкретные понятия составляют из более простых. Рассмотрим наследование на примере геометрических фигур, скажем, для некоторой гипотетической графической системы.
 
<?
class Shape { // фигура
 var $x;
 var $y;
 
 function Shape($x, $y) {
  $this->x = $x;
  $this->y = $y;
 }
 function get_x() { return $this->x; }
 function get_y() { return $this->y; }
} end of Shape
 
class Circle extends Shape { // окружность, потомок фигуры
 var $radius;
 
 function Circle($x, $y, $radius) {
  Shape::Shape($x, $y);
  $this->radius = $radius;
 }
 function get_radius() { return $this->radius; }
} // end of Circle
 
class Ring extends Circle { // кольцо, потомок окружности
 var $radius2;
 
 function Ring($x, $y, $radius, $radius2) {
  Circle::Circle($x, $y, $radius);
  if($radius2 < $radius) $radius2 = $radius;
  $this->radius2 = $radius2;
 }
 function get_radius2() { return $this->radius2; }
} end of Ring
 
// Создаем объекты Circle и Ring
$circle = new Circle(100, 100, 50);
$ring = new Ring(100, 100, 50, 60);
echo "кольцо:<br />n".
"координата x:".$ring->get_x()."<br />n".
"координата y:".$ring->get_y()."<br />n".
"внутренний радиус:".$ring->get_radius()."<br />n".
"внешний радиус:".$ring->get_radius2();
?>
 
Разберем этот пример детально. Сначала объявляем базовый класс для всех фигур - Shape. Общими свойствами всех фигур есть то, что они имеют какие-то координаты.
Значит так и указываем поля $x и $y с координатами для класса Shape, а конструктор лишь присваивает указанные координаты полям класса. Еще определяем два метода - get_x() и get_y(), возвращающие координаты $x и $y фигуры.
Дальше мы описываем потомка класса Shape - класс Circle (окружность). Окружность, кроме координат центра, имеет радиус, а остальные поля схожи с полями класса Shape.
 
Поэтому в объявлении класса пишем class Circle extends Shape (т.е. после имени класса потомка идет служебное слово extends и затем имя класса предка) тем самым указывая, что Circle - это потомок класса Shape и наследует все его поля и методы.
В описание добавляем еще одно поле $radius и немного изменяем конструктор - добавляем еще один параметр $radius и первым делом вызываем конструктор класса Shape (конструкция Shape::Shape($x, $y);), чтобы унаследовать всю его функциональность.
А именно - присвоение полям класса координат $x и $y. Методы get_x() и get_y() наследуются без изменений, но добавляется новый метод get_radius().
 
Поясню. В принципе, мы могли бы реализовать инициализацию полей $x и $y повторно в конструкторе Circle, и не пришлось бы вызывать унаследованный конструктор Shape. Но это ведь напрасная работа и затрата времени программиста, поскольку этот код уже у нас есть в конструкторе Shape и мы вправе его использовать в потомке.
 
Ведь проще вызвать унаследованный конструктор в самом начале тела конструктора потомка. Тем более это рациональнее, если представить себе, что родительский класс имеет, например, не 2 поля, а целую дюжину, или более того.
К тому же в родительском конструкторе могут быть скрыты какие-то нюансы, связанные с инициализацией полей. Так зачем нам снова в это вникать, если уже однажды мы этот код составили?
 
Именно этим и полезен ООП. Он позволяет избежать повторяющейся работы. Благодаря объектно-ориентированному подходу в программировании можно нагромождать код, используя и расширяя уже имеющуюся функциональность объектов.
При коммерческой разработке сайтов, форумов, магазинов и целых порталов это позволяет значительно сократить накладные расходы.
 
Аналогично на базе понятия "окружность" составляем еще более сложное понятие - "кольцо". Класс Ring в свою очередь наследует все поля и методы класса Circle, в том числе и те, что унаследованы от Shape. Добавляем еще поле для хранения величины внешнего радиуса $radius2, при этом выполняем проверку, не является ли он меньше внутреннего.
 
После объявления этих классов можем создать объекты, как показано в примере. После чего выполняется выдача значений полей объекта $ring:
 
кольцо:
координата x: 100
координата y: 100
внутренний радиус: 50
внешний радиус: 60
 
Как видим, невзирая на то, что мы не назначали непосредственно методы get_x(), get_y(), get_radius() и поля $x, $y, $radius для класса Ring, они работают, потому что были определены в родительских классах.
 
Этот подход имеет существенные преимущества. Вместо того, чтобы снова и снова создавать несколько классов со схожим поведением, мы реализуем лишь один базовый класс и несколько потомков от него, которые наследуют общее поведение (т.е. создали иерархию классов).
 
Такой принцип закладывает универсальность и легкость модернизации всех родственных классов. Например, если нам понадобится добавить для всех этих классов новое свойство, скажем, отвечающее за цвет фигуры, то достаточно будет добавить в описание класса Shape новое поле $color и оно будет сразу же унаследовано потомками этого класса и не возникнет необходимости исправлять каждый класс, как это пришлось бы делать, если бы такого понятия, как наследственность не существовало.
Думаю, теперь понятно, какую экономию времени дает это при разработке кода сложных систем.
 
Добавлю, что класс, который служит не для создания объектов, а лишь для построения на его основе более сложных классов (в данном случае - класс Shape), называется абстрактным.
 
Продолжение следует…
 
© Владислав Демьянишин
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > PHP и WEB для новичков (HTML, JavaScript, PHP, MySQL) > PHP и WEB для новичков (часть 7): Классы
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы