OKTOLOM |
Смерть - это только начало. Я часть той силы, что вечно хочет зла, и вечно совершает благо. И. Гёте. |
Место для Вашей рекламы icq:380014838 |
Полезные статьиНовые возможности PHP5/Zend Engine 2.0
Этот документ - достаточно вольный перевод статьи с официального сайта PHP - www.php.net. Если у вас нет проблем с английским языком, рекомендую ознакомиться с первоисточником. Обработка объектов в Zend Engine 2 полностью переработана: повышена производительность и добавлены новые возможности. В предыдущих версиях PHP объекты обрабатывались так же, как и переменные простых типов (например, целочисленные значения или строки). Недостаток такого подхода в том, что при присваивании (или передаче объекта как параметра функции) происходило копирование объекта. При новом подходе, объекты передаются по ссылке, а не по значению (если вам незнакома эта терминология, можете представить себе ссылку как уникальный идентификатор объекта). Многие PHP-программисты никогда не задумывались об аспекте копирования объекта, присущем старой объектной модели; следовательно, большинство существующих PHP-программ при переходе на PHP5 будут нормально работать без необходимости модификации кода, или же требуемая модификация будет весьма несущественной. В PHP5 введены частные (private) и защищенные (protected) переменные-элементы класса (member variables), что позволяет определять область их видимости. Защищенные (protected) переменные-элементы класса доступны методам (methods) класса, в котором они объявлены, и методам производного от него класса. Частные (private) элементы класса доступны только методам класса, в котором они объявлены.
function printHello() { class MyClass2 extends MyClass { $obj = new MyClass(); $obj = new MyClass2(); Частные и защищенные методы В PHP5 также введены частные (private) и защищенные (protected) методы.
protected function aProtectedMethod() { class Bar extends Foo { $o = new Bar; Существующие программы, не испольующие собственные классы или функции, названные "public", "protected" или "private", будут работать без каких-либо изменений.
class ImplementedClass extends AbstractClass { $o = new ImplementedClass; Создание экземпляра абстрактного класса невозможно. Существующие программы, не испольующие собственные классы или функции, названные "abstract", будут работать без каких-либо изменений. В PHP5 введены интерфейсы (interfaces). Класс может реализовывать произвольное число интерфейсов.
class Exception implements Throwable { Существующие программы, не испольующие собственные классы или функции, названные "interface" или "implements", будут работать без каких-либо изменений.
Оставаясь слабо типизированным языком, PHP5 предоставляет возможность использовать уточнения типа класса (class type hints) для указания ожидаемого класса объекта, передаваемого методу в качестве параметра. <?php interface Bar { class FooBar implements Foo, Bar { function b(Bar $bar) { $a = new FooBar; $a->a($b); Уточнения типов класса не проверяются не при компиляции, как в большинстве языков со строгой типизацией, а во время исполнения. Это означает, что следующие фрагменты кода эквивалентны: <?php Данный синтаксис применим только к объектам/классам, но не к встроенным типам данных.
Также возможно использовать ключевое слово "final" в определении самого класса, что запретит создание производных от него классов. При этом все элементы и методы такого класса автоматически являются финальными, и определять их таковыми явно нет необходимости.
// следующая строка вызовет ошибку времени выполнения Свойства не могут быть финальными. Существующие программы, не испольующие собственные классы или функции, названные "final", будут работать без каких-либо изменений. [fixxxer] Примечание: в PHP все методы класса являются виртуальными.
Данное поведение PHP4 не всегда позволяло достичь нужного результата. Хорошим примером необходимости конструктора копии является объект, представляющий GTK-окно и содержащий его ресурсы: при создании копии такого объекта, вам, скорее всего, хотелось бы создать новое окно с теми же свойствами, и получить объект, содержащий ресурсы нового окна. Еще один пример: объект хранит ссылку на другой используемый им объект, и при создании копии хотелось бы получить ссылку на новый экземпляр объекта, а не на тот же. Для создания копии объекта, вызывается его метод __clone(): При выполнении данной операции, PHP5 сначала проверит, определен ли метод __clone(). Если он не определен, PHP вызовет метод __clone(), созданный под умолчанию, который осуществит побайтное копирование всех свойств объекта. В случае же, если метод __clone() определен, он отвечает за установку требуемых свойств создаваемой копии объекта. Для удобства, Zend Engine предоставляет функцию, импортирующую все свойства копируемого объекта, так что достаточно переопределить только те свойства, которые необходимо изменить.
function MyCloneable() { function __clone() { $obj = new MyCloneable(); $obj->name = "Hello"; print $obj->id . "\n"; $obj = $obj->__clone(); print $obj->id . "\n"; Единое имя конструкторов В PHP4 конструктором явзяется метод, который называется так же, как сам класс. Так как часто необходимо вызывать конструктор базового класса из класса производного, такой принцип именования конструкторов затрудняет работу со сложной иерархией классов. Если базовый класс изменен, приходится также менять имя вызываемого конструктора базового класса в коде производного класса. В PHP5 введен стандартный способ объявления конструктора класса. Конструктором в PHP5 является метод с именем __construct().
class SubClass extends BaseClass { $obj = new BaseClass(); Для обратной совместимости, предусмотрено следующее: если PHP5 не находит функцию __construct() в определении данного класса, используется старый стиль именования конструкторов. Таким образом, единственный случай несовместимости при переходе на PHP5 - присутствие в объявлении класса метода с именем __construct(). Возможность объявления деструкторов может быть весьма полезной. Деструктор может вести лог отладочных сообщений, закрывать соединения с базой данных и т.п. В PHP4 отсутствовала поддержка деструкторов, хотя имелась возможность указать функцию, которая вызывается при завершении работы скрипта. PHP5 поддерживает деструкторы, аналогично другим объектно-ориентированным языкам, таким как Java. Когда последняя ссылка на объект уничтожена, прежде, чем память, выделенная объекту, уничтожается, вызывается метод класса с именем __destruct() без каких-либо параметров.
function __destruct() { $obj = new MyDestructableClass(); Подобно конструкторам, деструкторы базовых классов не вызываются автоматически. Для вызова деструктора базового класса необходимо явно указать вызов метода parent::__destruct() в коде деструктора. [fixxxer] Примечание: само собой разумеется, при портировании PHP4-скриптов возможной несовместимостью будет наличие методов __destruct(), используемых в других целях. Видимо, в связи с мизерной вероятностью такого случая разработчики не сочли нужным об этом упомянуть. В PHP5 введены константы-элементы класса: <?php echo "Foo::constant = " . Foo::constant . "\n"; Существующие программы, не испольующие собственные классы или функции, названные "const", будут работать без каких-либо изменений. В PHP4 не было обработки исключений. В PHP5 реализована обработка исключений, подобно другим языкам программирования. Обратите внимание на поддержку инструкций "catch all" и "finally". Исключения можно повторно посылать из блоков catch. Также, возможно наличие нескольких блоков catch. В этом случае, полученное исключение обрабатывается первым по порядку блоком catch, instanceof которого совпадает с типом класса, экземпляром которого является исключение. При завершении работы блока catch, выполнение программы продолжается с инструкции, следующей за последним блоком catch. Если ни одного подходящего по "instanceof" блока catch не обнаружено, продолжается поиск других блоков try/catch. Если же и этот поиск не увенчается успехом, исключение считается необработанным, выводится сообщение об ошибке, и выполнение программы прерывается.
class MyExceptionFoo extends MyException { function Display() { try { Несмотря на то, что вышеприведенный пример демонстрирует возможность определения исключения как элемента класса, не являющегося производным от класса Exception, так делать не рекомендуется, так как встроенный класс Exception позволяет собрать и вывести информацию, иначе недоступную. Примером использования данной возможности является нижеприведенный код, снабженный комментариями, описывающими каждое свойство и, соответственно, методы, используемые для чтения их значений. Так как некоторые методы используются для внутренних целей, они объявлены финальными (final). Вообще, в объявлении класса Exception довольно много ограничений, так как необходимо гарантировать совпадение ожидаемого результата с действительным.
protected $message = 'Unknown exception'; // текст сообщения об исключении private $trace; // backtrace исключения final function getMessage() { Если вы создадите ваши собственные классы исключений как производные от приведенного класса Exception, встроенный обработчик необработанных исключений выведет о них подробную информацию. Существующие программы, не испольующие собственные классы или функции, названные "catch", "throw" или "try", будут работать без каких-либо изменений. В PHP4 не было возможности разыменования (dereferencing) объектов, возвращаемых фунцией. В PHP5 такая возможность введена, что позволяет вызывать методы возвращаемых объектов, оперируя непосредственно с результатом выполнения функции:
function ShapeFactoryMethod($shape) { ShapeFactoryMethod("Circle")->draw();
Пример: <?php print foo::$my_static;
Foo::aStaticMethod(); Псевдо-переменная $this внутри метода, объявленного статическим, недоступна (так как при вызове статического метода неизвестно, в контексте какого экземпляра класса ее использовать, да и вполне возможно, что на момент вызова их не существует вообще - [fixxxer]). В PHP5 введено ключевое слово instanceof, позволяющее определить, является или не является объект экземпляром класса, экземпляром, производным от класса, или же реализацией интерфейса.
$a = new baseClass; if ($a instanceof basicClass) {
Статические переменные теперь обрабатываются на этапе компиляции, что позволяет присваивать им значения по ссылке. Это изменение также значительно повышает производительность, но означает, что косвенные ссылки на статические переменные больше не будут работать. Пример:
Функция __autoload() вызывается автоматически в случае, когда происзодит попытка создания неопределенного класса. Имя класса передается функции __autoload() в качестве единственного аргумента. $object = new ClassName;
Как вызовы методов, так и операции доступа к свойствам могут быть перегружены с использованием методов __call(), __get() и __set(). function __get($nm) { if (isset($this->x[$nm])) { function __set($nm, $val) { if (isset($this->x[$nm])) { $foo = new Setter(); function __call($m, $a) { $foo = new Caller();
Для объекта можно указать итератор, который будет использован при применении класса в операторе foreach. По умолчанию итерация происходит путем перебора всех свойств. $obj = new Foo; foreach ($obj as $prp_name => $prop_value) { Каждый класс, экземпляры которого можно использовать с оператором foreach, должен реализовывать пустой интерфейс Traversable. Другими словами, любой объект, котороый реализует Traversable, можно использовать с foreach. Интерфейсы IteratorAggregate и Iterator позволяют указать поведение класса при его использовании с оператором foreach. Первый интерфейс предоставляет единственный метод getIterator(), который должен возвращать массив или объект, который либо реализует интерфейс Iterator, либо является объектом встроенного класса, имеющего итератор. private $obj; function __construct($obj) { class Object implements IteratorAggregate { public $max = 3; function getIterator() { $obj = new Object; // this foreach ... // matches the following 7 lines with the for directive. Данный пример весьма интерестен, так как демонстрирует использование всех абстрактных методов, объявленных в интерфейсах Iterator и IteratorAggregate соответственно.
Новая псевдо-константа __METHOD__ содержит текущие имена класса и метода, если используется внутри метода, и имя функции, если используется вне класса.
Новый метод __toString() позволяет перегрузить преобразование типа "объект->строка". $obj = Foo; $str = (string) $obj; // вызывается __toString() echo $obj; // вызывается __toString() К сожалению, на данный момент метод _toString работает только при использовании в контексте оператора echo/print. PHP5 включает в себя reflection API, предоставляющий возможность реверс-инжиниринга классов, интерфейсов, функций, методов, а также расширений (extensions). Reflection API также предоставляет доступ к doc-комментариям функций, классов и методов. Практически все аспекты ОО-кода могут быть отражены с помощью reflection API. Reflaction API документируется отдельно. reflection_class::export('Foo');
В PHP5 используется новый диспетчер памяти, более эффективно работающий в мультитрэдовой среде, так как он не использует мутексы (mutexes) для осуществления блокирования/разблокирования (lock/unlock) при операциях выделения/освобождения памяти (allocation/deallocation). |