Russian version
English version
ОБ АЛЬЯНСЕ | НАШИ УСЛУГИ | КАТАЛОГ РЕШЕНИЙ | ИНФОРМАЦИОННЫЙ ЦЕНТР | СТАНЬТЕ СПОНСОРАМИ SILICON TAIGA | ISDEF | КНИГИ И CD | ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ | УПРАВЛЕНИЕ КАЧЕСТВОМ | РОССИЙСКИЕ ТЕХНОЛОГИИ | НАНОТЕХНОЛОГИИ | ЮРИДИЧЕСКАЯ ПОДДЕРЖКА | АНАЛИТИКА | КАРТА САЙТА | КОНТАКТЫ
 
Программное обеспечение
 
Для зарегистрированных пользователей
 
РАССЫЛКИ НОВОСТЕЙ
IT-Новости
Новости компаний
Российские технологии
Новости ВПК
Нанотехнологии
 
Поиск по статьям
 
RSS-лента
Подписаться
Интернет

Введение в PHP5

Данил Миронов

Оригинал статьи: http://www.phpbuilder.com/columns/argerich20030411.php3
Автор: Luis Argerich

PHP5 ещё официально не вышел, но "рабочие" версии уже трудоспособны (равно как и нестабильны!), так что мы вполне можем начать изучение новых возможностей грядущего релиза PHP и попрактиковать с ними. В этой статье мы поговорим о трёх основных нововведениях в PHP5:

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

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

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

PHP5 ещё не выпущен и мне неизвестно, когда это произойдёт, но уже сейчас вы можете потестировать и изучить новые возможности языка, скачав рабочую версию PHP5 с http://snaps.php.net и установив её. По этой ссылке вы можете найти готовые для установки Windows и Linux версии PHP5. Инсталляция проходит как у любого нормального релиза PHP, так что все бегом за новой игрушкой.

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

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

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

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

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

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

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: Объекты как ссылки

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: Клонирование объектов

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

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: Интерфейсы

interface displayable {
function display ();
}

interface printable {
function doprint ();
}

class foo implements displayable , printable {
function display () {
// код
}

function doprint () {
// код
}
}
?>

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

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

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

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

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

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

class foo {

function __call ( $name , $arguments ) {
print( "Вызывали? Я - $name!" );
}
}

$x = new foo ();
$x -> doStuff ();
$x -> fancy_stuff ();
?>

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

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

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

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: указание типов

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: методы класса и переменные класса

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: Исключения

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
\n" ;
// Какие-нибудь драконовские меры
}
?>

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

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

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

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

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: Пространство имён

namespace Math {

class Complex {
//...код...
function __construct () {
print( "привет" );
}
}
}

$m = new Math :: Complex ();
?>

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


  Рекомендовать страницу   Обсудить материал Написать редактору  
  Распечатать страницу
 
  Дата публикации: 01.09.2006  

ОБ АЛЬЯНСЕ | НАШИ УСЛУГИ | КАТАЛОГ РЕШЕНИЙ | ИНФОРМАЦИОННЫЙ ЦЕНТР | СТАНЬТЕ СПОНСОРАМИ SILICON TAIGA | ISDEF | КНИГИ И CD | ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ | УПРАВЛЕНИЕ КАЧЕСТВОМ | РОССИЙСКИЕ ТЕХНОЛОГИИ | НАНОТЕХНОЛОГИИ | ЮРИДИЧЕСКАЯ ПОДДЕРЖКА | АНАЛИТИКА | КАРТА САЙТА | КОНТАКТЫ

Дизайн и поддержка: Silicon Taiga   Обратиться по техническим вопросам  
Rambler's Top100 Rambler's Top100