Распечатать статью

Введение в PHP5

В этой статье мы поговорим о трёх основных нововведениях в PHP5:

* Новая объектная модель
* Исключения
* Пространства имён

Но сначала пара официальных заявлений:

* Некоторые из приведённых в данной статье решений воспроизводимы в PHP4, но, тем не менее, их описание присутствует и здесь для большей удобочитаемости и целостности всей статьи.
* Некоторые из описанных в данной статье особенностей в конечном релизе PHP5 могут быть изменены.

Новая объектная модель

В PHP5 объектную модель основательно подлатали и добавили много новых возможностей, благодаря чему PHP5 стал «чем-то» напоминать Java. В этой части нашей статьи будет описана эта новая объектная модель и приведено несколько небольших примеров, чтобы вам обозначить исходный рубеж для ваших экспериментов.

* Конструкторы и деструкторы
* Объекты как ссылки
* Клонирование объектов
* Дескрипторы Private, Public и Protected
* Интерфейсы
* Абстрактные классы
* __call
* __set and __get
* Закрытые члены

Конструкторы и деструкторы

В PHP4 конструктор именуется так же как и сам класс, а деструкторы отсутствуют полностью.

В PHP5 конструктор класса именуется __construct, а деструктор — __destruct.

Пример 1: Конструкторы и деструкторы

<?php class foo { var $x; function __construct($x) { $this->x = $x; } function display() { print($this->x); } function __destruct() { print("ну, пока, до скорого"); } } $o1 = new foo(4); $o1->display(); ?>

Как вы видите, деструктор вызывается перед самым уничтожением класса.

Объекты как ссылки

Как вам уже наверняка известно, в PHP4 переменные передаются в функции/методы по значению (передаётся копия), если в объявлении функции не поставлен символ ‘&’, указывающий на то, что переменная должна передаваться как ссылка. В PHP5 объекты передаются всегда как ссылки. Присваивание объектов тоже происходит по ссылке.

Пример 2: Объекты как ссылки

<?php class foo { var $x; function setX($x) { $this->x = $x; } function getX() { return $this->x; } } $o1 = new foo; $o1->setX(4); $o2 = $o1; $o1->setX(5); if($o1->getX() == $o2->getX()) print("Ох ты, Боже мой!"); ?>

 

Клонирование объектов

Если объекты присваиваются и передаются по ссылке, то вам нужно как-то создавать и копии объектов. Для этого используйте метод __clone.

Пример 3: Клонирование объектов

<?php class foo { var $x; function setX($x) { $this->x = $x; } function getX() { return $this->x; } } $o1 = new foo; $o1->setX(4); $o2 = $o1->__clone(); $o1->setX(5); if($o1->getX() != $o2->getX()) print("Копии взаимонезависимы"); ?>

В программировании клонирование разрешено, так что всё легально 😉

Дескрипторы Private, Public и Protected

В PHP4 все методы и переменные внутри объекта были доступны извне, другими словами все методы и переменные всегда были открытыми. В PHP5 вводится три дескриптора для осуществления контроля над доступом к переменным и методам: Public, Protected и Private.

* Public (открытый): Метод/переменная доступны из любого места в коде.
* Private (закрытый): Закрытые методы или переменные доступны только внутри класса.
* Protected (защищённый): Защищённые методы или переменные доступны только внутри класса, где они были объявлены и из его производных классов.

Пример 4: Public, protected and private

<?php class foo { private $x; public function public_foo() { print("Это открытый метод"); } protected function protected_foo() { $this->private_foo(); //Всё правильно, мы можем вызывать закрытые методы, потому что мы находимся в том же классе print("Это защищённый метод"); } private function private_foo() { $this->x = 3; print("Это закрытый метод"); } } class foo2 extends foo { public function display() { $this->protected_foo(); $this->public_foo(); // $this->private_foo(); // Неправильно! В базовом классе метод закрыт } } $x = new foo(); $x->public_foo(); //$x->protected_foo(); //Неправильно, защищённые методы могут вызываться только из того же класса или его производных классов //$x->private_foo(); //Неправильно, закрытые методы могут быть вызваны только в классе, где они были объявлены $x2 = new foo2(); $x2->display(); ?>

Совет разработчикам: Переменные класса всегда следует делать закрытыми, прямой доступ к переменным — не очень хорошая практика в ООП, лучше всего для доступа/изменения переменных класса определять специальные методы.

Интерфейсы

Как вы знаете, PHP4 поддерживает наследование классов синтаксисом «class foo extends parent». В PHP4 И в PHP5 класс может наследовать только один класс, то есть множественное наследование не поддерживается. Интерфейсом называется класс, в котором не реализуется ни один метод, определяются только названия методов и набор передаваемых им параметров. Впоследствии классы могут ‘реализовывать’ сколь угодно много интерфейсов, показывая тем самым, что тот или иной класс реализует методы, определённые в интерфейсе.

Пример 5: Интерфейсы

<?php interface displayable { function display(); } interface printable { function doprint(); } class foo implements displayable,printable { function display() { // код } function doprint() { // код } } ?>

Использование интерфейсов полезно для более удобного чтения и понимания кода: прочитав объявление класса, мы увидим, что класс реализует интерфейсы displayable и printable; это означает, что класс должен иметь методы display() и doprint(). Как эти методы реализованы — значения не имеет, главное — уже из объявления класса, вы знаете, что можете вызывать эти методы.

Абстрактные классы

Абстрактным называется класс, который может использоваться только как базовый (то есть создавать объекты этого класса нельзя). Как и в любом нормальном базовом классе, в абстрактном классе вы можете определять методы и переменные.

В абстрактном классе также можно определять абстрактные методы: методы, которые не реализованы в абстрактном классе, но которые обязательно должны быть реализованы в производных классах.

Пример 6: Абстрактные классы

<?php abstract class foo { protected $x; abstract function display(); function setX($x) { $this->x = $x; } } class foo2 extends foo { function display() { // Код } } ?>

 

__call

С PHP5 вы можете реализовать в классе специальный метод __call(), как метод для «отлова» всех нереализованных в данном классе методов. Метод __call (если он определён) вызывается при попытке вызвать недоступный или несуществующий метод.

Пример 7: __call

<?php class foo { function __call($name,$arguments) { print("Вызывали? Я - $name!"); } } $x = new foo(); $x->doStuff(); $x->fancy_stuff(); ?>

Этот специальный метод может быть использован для реализации перегрузки методов: вы можете исследовать полученные аргументы и в зависимости от результата вызвать подходящий для данного случая закрытый метод, например:

Пример 8: Перегрузка методов с помощью __call

<?php class Magic { function __call($name,$arguments) { if($name=='foo') { if(is_int($arguments[0])) $this->foo_for_int($arguments[0]); if(is_string($arguments[0])) $this->foo_for_string($arguments[0]); } } private function foo_for_int($x) { print("у, смотрите, целое число!"); } private function foo_for_string($x) { print("у, смотрите, строка!"); } } $x = new Magic(); $x->foo(3); $x->foo("3"); ?>

 

__set и __get

Но это ещё не всё, теперь вы можете определить методы __set и __get для «отлова» всех попыток изменения или доступа к неопределённым (или недоступным) переменным.

Пример 9: __set и __get

<?php class foo { function __set($name,$val) { print("Привет, вы попытались присвоить значение $val переменной $name"); } function __get($name) { print("Привет, вы пытались обратиться к $name"); } } $x = new foo(); $x->bar = 3; print($x->winky_winky); ?>

Указание типов для аргументов

В PHP5 вы сможете «сказать» методу, что он должен получить в качестве аргумента объект определённого типа.

Пример 10: указание типов

<?php class foo { // код ... } class bar { public function process_a_foo(foo $foo) { // Ещё какой-нибудь код } } $b = new bar(); $f = new foo(); $b->process_a_foo($f); ?>

Как вы заметили, перед именем аргумента теперь можно поставить имя его класса, и таким образом PHP5 определит, что переменная $foo должна быть класса foo.

Статические члены класса

Статические члены и статические методы могут использоваться для реализации того, что в ООП называется «методы класса» и «переменные класса».

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

Пример 11: методы класса и переменные класса

<?php class calculator { static public $pi = 3.14151692; static public function add($x,$y) { return $x + $y; } } $s = calculator::$pi; $result = calculator::add(3,7); print("$result"); ?>

 

Исключения

Исключения — это общепринятый подход к обработке ошибок и неожиданных ситуаций в таких языках как Java и C++; в PHP5 перехват исключений реализован с помощью пары «try» — «catch».

Пример 12: Исключения

<?php class foo { function divide($x,$y) { if($y==0) throw new Exception("деление на ноль недопустимо"); return $x/$y; } } $x = new foo(); try { $x->divide(3,0); } catch (Exception $e) { echo $e->getMessage(); echo "n<br />n"; // Какие-нибудь драконовские меры } ?>

Как вы видите, «try» используется для обозначения блока, в котором находятся ошибки, обрабатываемые оператором «catch», стоящим в конце блока. В блоке «catch» вам нужно реализовать вашу собственную политику обработки ошибок. В итоге получаем удобочитаемый код и всего один блок обработки ошибок.

Исключения, определённые пользователем

Для обработки непредвиденных проблем в ваших программах вы можете определить ваши собственные исключения. Всё, что вам нужно — это просто дополнить (extend) класс Exception, определив конструктор класса и метод getMessage.

Пример 13: Исключения, определённые пользователем

<?php class WeirdProblem extends Exception { private $data; function WeirdProblem($data) { parent::exception(); $this->data = $data; } function getMessage() { return $this->data . " вызвало какое-то странное исключение!"; } } ?>

Потом, для возбуждения определённого вами исключения используйте конструкцию throw new WeirdProblem($foo); если исключение происходит внутри блока try{}, то PHP5 передаст управление в «catch»-блок для обработки.

Пространства имён

В целях удобства классы и функции могут быть сгруппированы в пространства имён (namespaces).

Примечение: разработчики отказались от поддрежки этой возможности.

Пример 14: Пространство имён

<?php namespace Math { class Complex { //...код... function __construct() { print("привет"); } } } $m = new Math::Complex(); ?>

Обратите внимание на синтаксис использования именного пространства для обозначения класса, объект которого мы создаём. Пример практического применения: создание одноимённых классов в разных именных пространствах; при этом классы делают отличную друг от друга работу (имея одинаковый интерфейс).

Источник: internet-technologies.ru

Вы можете оставить комментарий, или обратную ссылку на Ваш сайт.

Оставить комментарий

Похожие статьи