Работа с классом
Класс, который используется в сценарии, должен быть в него каким-то образом добавлен. Обычно он размещается в отдельном файле и с помощью функции include() подключается к основному сценарию.
Для того чтобы использовать объект, его необходимо сначала создать. После этого объект может выполнять любые методы, определенные в классе. Процесс создания объектов называется инстанцированием (instantiation). Аналогично тому, как выкройка используется для шитья большого количества похожей, но все же по-своему индивидуальной одежды, точно так же на основе классов создаются объекты. Для создания объекта используется следующий синтаксис:
$имя_объекта = new имяКласса(значение, значение, . . . ) ; $Joe = new Person("мужчина"); $car_Joe = new Car("красный"); $car_Sam = new Car("зеленый"); $customer1 = new Customer("Смит", "Джо", $custID);
При создании объекта вызывается конструктор, в результате чего объект связывается с переменной с заданным именем. После этого для вызова метода класса можно воспользоваться следующими выражениями:
$Joe->goToWork(); $car_Joe->park("запрещено"); $car_Sam->paintCar("синий"); $name = $customerl->getName ();
Разные объекты, созданные на основе одного и того же класса, независимы друг от друга. Например, если автомобиль Сэма перекрасить в голубой цвет, то автомобиль Джо никак не изменит свой цвет и будет оставаться красным. Джо покупает талон для парковки, но это никак не повлияет на Сэма (и на его автомобиль).
В листинге ниже приведен пример использования класса Form, который был создан в предыдущем разделе:
‹?php /* Имя сценария: buildForm * Описание: использование класса Form для создания * простой HTML-формы. */ require_once ("form, inc"); echo "<html><head><title>Форма для добавления телефонного номepa</titlex/head><body>" ; $phone_form = new Form("process.php", "Отправить данные"); $phone_form->addField("first_name", "Имя"); $phone_form->addField("last_name", "Фамилия"); $phone_form->addField("phone", "Номер телефона"); echo "<hЗ>Пожалуйста, заполните поля данной формы:</h3>"; $phone_form->displayForm(); echo "</body></html>" ; ?›
|
Сначала с помощью функции require_once() файл form.inc с описанием класса Form включается в сценарий. На его основе создается объект с именем $phone_form. 3aтем в форму добавляются три поля, после чего форма выводится на экран. Следует заметить, что в приведенном фрагменте использовалось несколько дополнительных дескрипторов HTML, которые можно было бы разместить и в методе displayForm(). При выполнении приведенного сценария с использованием класса Form будет создана форма с тремя полями.
Скрытые свойства и методы
Свойства и методы класса могут быть как открытыми (public), так и закрытыми (private). Открытые свойства и методы доступны извне класса, т.е. из сценария, в котором используется данный класс, или из другого класса. Рассмотрим пример класса, атрибут и метод которого являются открытыми:
class Car { var $gas = 0; function addGas($amount) { $this->gas = $this->gas + $amount; echo "в бак залито $amount галлонов бензина"; } }
Теперь к открытому атрибуту класса $gas можно получить доступ из-за его пределов следующим образом:
$mycar = new Car; $gas_amount = $mycar->gas;
После выполнения этого фрагмента в переменной $gas_amount будет содержаться значение атрибута $gas объекта mycar. Значение атрибута можно также и изменить извне класса:
$mycar->gas = 20; Прямой доступ к атрибутам класса считается плохим стилем программирования. Любое взаимодействие объекта и внешнего сценария или другого класса должно осуществляться лишь посредством методов. Метод addGas() из приведенного класса Саr является открытым и применяется для "заправки" автомобиля (т.е. для увеличения значения атрибута $gas):
$new_car = new Car; $new_car->addGas(5);
Язык PHP позволяет ограничить доступ к атрибутам и методам класса. Это можно осуществить следующими способами:
- Спецификатор private (закрытый) запрещает доступ к атрибутам и методам класса из-за пределов класса, сценариев или других классов.
- Спецификатор protected (защищенный) предоставляет доступ к защищенным свойствам и методам класса только для его классов-наследников. В остальных случаях доступ запрещен.
Для того чтобы атрибут стал скрытым, следует воспользоваться выражением:
private $gas = 0; При попытке прямого доступа к скрытому атрибуту отобразится следующее сообщение об ошибке:
Fatal error: Cannot access private property car::$gas in c:\test class.php on line 17 (Фатальная ошибка: Нельзя получить доступ к закрытому атрибуту car::$gas в файле c:\testclass.php в строке 17)
Теперь изменить значение атрибута $gas класса Саr можно только с помощью метода addGas(), поскольку он является частью класса Саr и, следовательно, имеет доступ к соответствующему скрытому атрибуту.
Подобно атрибутам, методы класса также могут быть скрытыми (private) или защищёнными (protected). Однако в классе Саr метод addGas() является открытым. В реальных программах нужно быть уверенным в том, что за бензин, которым заправлен автомобиль, уплачено и что он не взялся неизвестно откуда (например, был украден). Поэтому класс Саr следует переписать следующим образом:
class Car { private $gas = 0; private function addGas($amount) { $this->gas = $this->gas + $amount; echo "в бак залито $amount галлонов бензина"; } function buyGas($amount) { $this->addGas($amount); } }
Теперь единственный возможный способ изменения значения атрибута $gas класса Саr (т.е. заправки автомобиля) заключается в использовании метода buyGas(). В свою очередь, этот метод использует скрытый метод addGas(). Прямой вызов метода addGas() приведет к возникновению ошибки.
$new_car = new Car; $new_car->addGas(5);
Для того чтобы этого не произошло, необходимо воспользоваться методом buyGas(): $new_car = new Car; $new_car->buyGas(5);
В результате получим следующий результат: в бак залито 5 галлонов бензина Хороший стиль программирования заключается в сокрытии как можно большего количества деталей реализации класса. Все атрибуты должны быть скрытыми (private), а методы (те из них, которые должны быть открытыми) — public.
В языке РНР атрибуты и методы класса могут быть объявлены открытыми несколькими способами. Это связано с тем, что по умолчанию уровень доступа является открытым. Так, выражени
public $gas = 0; равносильно var $gas = 0;
Использование исключенийДля обработки ошибок в языке РНР используется класс Exception (исключение). Его можно применять для обработки нежелательных событий, которые могут возникнуть в сценарии. Если возникает заранее определенная разработчиком ситуация, то выполняется соответствующая процедура ее обработки. С точки зрения объектно-ориентированного подхода этот процесс называется генерацией исключения.
В классе Саr автомобиль может двигаться до тех пор, пока в его баке есть горючее (т.е. $gas>0). Поэтому сценарий должен правильно реагировать на ситуацию, когда значение атрибута $gas станет отрицательным. Это и будет исключением. Для его обработки необходимо воспользоваться классом Exception с помощью следующего фрагмента кода:
$this->gas = $this->gas - 5; try { if ($this->gas < 0) { throw new Exception("Отрицательное количество бензина. " ) ; } } catch (Exception $e) { echo $e->getMessage(); echo "\n<br />\n"; exit(); }
В приведенном фрагменте содержатся блоки try и catch. В блоке try выполняется проверка условия. Если результат проверки условия — TRUE, то генерируется исключение, т.е. создается новый объект класса Exception. Этот объект имеет атрибут, в котором хранится сообщение, которое будет использоваться при генерации исключения. В блоке catch исключение перехватывается, и ему присваивается имя $е. После этого выполняется обработка исключения. В частности, вызывается метод getMesssage() класса Exception. Этот метод возвращает сообщение, заданное при создании объекта Exception, которое выводится с помощью функции echo.
Если исключение не сгенерировано, блок catch игнорируется, а выполнение сценария продолжается.
Копирование объектовДля копирования объектов в языке РНР используется специальный метод __clone() (с двумя символами подчеркивания). При необходимости этот метод можно переопределить. По умолчанию (т.е. без переопределения) метод __clone() просто скопирует все атрибуты одного объекта в атрибуты другого объекта. Рассмотрим следующий класс с переопределенным методом __clone():
class Car { private $gas = 0; private $color = "красный"; function addGas($amount) { $this->gas = $this->gas + $amount; echo "в бак залито $amount галлонов бензина"; } function __clone() { $this->gas = 0; } }
Используя этот класс, можно создать объект, а затем скопировать его следующим образом: $firstCar = new Car; $firstCar->addGas(10); $secondCar=$firstCar->__clone();
После выполнения этого фрагмента кода будут созданы два объекта класса Саr. - $firstCar. Этот автомобиль имеет красный цвет и 10 галлонов бензина, которые были добавлены с помощью метода addGas().
- $secondCar. Этот автомобиль также имеет красный цвет, но 0 галлонов бензина. Объект $secondCar был создан как копия $firstCar с помощью вызова метода __clone(), который присваивает переменной $gas значение 0 и вообще не устанавливает цвет ($color).
Если в классе Саr не переопределить метод __clone(), интерпретатор РНР создаст его самостоятельно, по умолчанию скопировав все атрибуты объекта $firstCar в $secondCar, т.е. автомобиль $secondCar, как и $f irstCar, будет иметь красный цвет и 10 галлонов бензина.
Удаление объектовУдалить ранее созданный объект можно следующим образом: unset($objName); Ниже приведен пример, в котором объект класса Саr создается, а затем удаляется. $myCar = new Car; unset($myCar);
После вызова функции unset() объект больше не существует. В РНР имеется специальный метод __destruct(), который автоматически вызывается при удалении объекта. Ниже приведен класс, содержащий этот метод.
class Bridge { function __destruct() { echo "Мост разрушен"; } }
При создании объекта класса Bridge, а затем его удалении $bigBridge = new Bridge; unset($bigBridge); отобразится следующее сообщение: Мост разрушен Оно отображается вследствие вызова метода __destruct() при вызове функции unset(). Метод __destruct() не является обязательным. По необходимости его можно переопределить, как методы __construct () и __clone(), и выполнить некоторые специфические действия при удалении объекта. Например, при удалении объекта может потребоваться закрыть некоторые файлы или переписать информацию в базу данных.
|