Разыменование объектов, возвращаемых функцией

В PHP4 не было возможности разыменования (dereferencing) объектов, возвращаемых фунцией. В PHP5 такая возможность введена, что позволяет вызывать методы возвращаемых объектов, оперируя непосредственно с результатом выполнения функции:

class Circle {
 function draw() {
 print "Circlen";
 }
}
 
class Square {
 function draw() {
 print "Squaren";
 }
}

function ShapeFactoryMethod($shape) {
 switch ($shape) {
 case "Circle": 
 return new Circle();
 case "Square": 
 return new Square();
 }
}

ShapeFactoryMethod("Circle")->draw();
ShapeFactoryMethod("Square")->draw();
?>

Инициализация статических переменных-элементов статических классов

Пример:

class foo {
 static $my_static = 5;
 public $my_prop = 'bla';
}

print foo::$my_static;
$obj = new foo;
print $obj->my_prop;
?>

Статические методы

В PHP5 ключевое слово "static" можно использовать для определения статического метода, что позволяет вызывать метод вне контекста объекта.

Пример:

class Foo {
 public static function aStaticMethod() {
 // ...
 }
}

Foo::aStaticMethod();
?>

Псевдо-переменная $this внутри метода, объявленного статическим, недоступна (так как при вызове статического метода неизвестно, в контексте какого экземпляра класса ее использовать, да и вполне возможно, что на момент вызова их не существует вообще - [fixxxer]).

Ключевое слово instanceof

В PHP5 введено ключевое слово instanceof, позволяющее определить, является или не является объект экземпляром класса, экземпляром, производным от класса, или же реализацией интерфейса.

Пример:

class baseClass { }

$a = new baseClass;

if ($a instanceof basicClass) {
 echo "Hello World";
}
?>

Статические переменные функций

Статические переменные теперь обрабатываются на этапе компиляции, что позволяет присваивать им значения по ссылке. Это изменение также значительно повышает производительность, но означает, что косвенные ссылки на статические переменные больше не будут работать.

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

Пример:

function my_function(&$var = null) {
 if ($var === null) {
 die("$var needs to have a value");
 }
}
?>

__autoload()

Функция __autoload() вызывается автоматически в случае, когда происзодит попытка создания неопределенного класса. Имя класса передается функции __autoload() в качестве единственного аргумента.

Пример:

function __autoload($className) {
 include_once $className . ".php";
}

$object = new ClassName;
?>

Перегрузка вызовов метода и доступа к свойствам

Как вызовы методов, так и операции доступа к свойствам могут быть перегружены с использованием методов __call(), __get() и __set().

Пример: __get() и __set()

class Setter {
 public $n;
 public $x = array("a" => 1, "b" => 2, "c" => 3);

 function __get($nm) {
 print "Getting [$nm]n";

 if (isset($this->x[$nm])) {
 $r = $this->x[$nm];
 print "Returning: $rn";
 return $r;
 } else {
 print "Nothing!n";
 }
 }

 function __set($nm, $val) {
 print "Setting [$nm] to $valn";

 if (isset($this->x[$nm])) {
 $this->x[$nm] = $val;
 print "OK!n";
 } else {
 print "Not OK!n";
 }
 }
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;
var_dump($foo);
?>

Пример: __call()

class Caller {
 var $x = array(1, 2, 3);

 function __call($m, $a) {
 print "Method $m called:n";
 var_dump($a);
 return $this->x;
 }
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>

Итераторы

Для объекта можно указать итератор, который будет использован при применении класса в операторе foreach. По умолчанию итерация происходит путем перебора всех свойств.

Пример:

class Foo {
 var $x = 1;
 var $y = 2;
}

$obj = new Foo;

foreach ($obj as $prp_name => $prop_value) {
 // using the property
}
?>

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

Интерфейсы IteratorAggregate и Iterator позволяют указать поведение класса при его использовании с оператором foreach. Первый интерфейс предоставляет единственный метод getIterator(), который должен возвращать массив или объект, который либо реализует интерфейс Iterator, либо является объектом встроенного класса, имеющего итератор.

Пример:

class ObjectIterator implements Iterator {

 private $obj;
 private $num;

 function __construct($obj) {
 $this->obj = $obj;
 }
 function rewind() {
 $this->num = 0;
 }
 function hasMore() {
 return $this->num < $this->obj->max;
 }
 function key() {
 return $this->num;
 }
 function current() {
 switch($this->num) {
 case 0: return "1st";
 case 1: return "2nd";
 case 2: return "3rd";
 default: return $this->num."th";
 }
 }
 function next() {
 $this->num++;
 }
}

class Object implements IteratorAggregate {

 public $max = 3;

 function getIterator() {
 return new ObjectIterator($this);
 }
} 

$obj = new Object;

// this foreach ...
foreach($obj as $key => $val) {
 echo "$key = $valn";
}

// matches the following 7 lines with the for directive.
$it = $obj->getIterator();
for($it->rewind(); $it->hasMore(); $it->next) {
 $key = $it->current();
 $val = $it->key();
 echo "$key = $valn";
}
unset($it);
?>

Данный пример весьма интерестен, так как демонстрирует использование всех абстрактных методов, объявленных в интерфейсах Iterator и IteratorAggregate соответственно.

Новая константа __METHOD__

Новая псевдо-константа __METHOD__ содержит текущие имена класса и метода, если используется внутри метода, и имя функции, если используется вне класса.

Пример:

Example

class Foo {
 function Show() {
 echo __FILE__ . '(' . __LINE__ . ')' . __METHOD__;
 }
}
function Test() {
 echo __FILE__ . '(' . __LINE__ . ')' . __METHOD__;
}
?>

Новый метод __toString()

Новый метод __toString() позволяет перегрузить преобразование типа "объект->строка".

Пример:

class Foo {
 function __toString() {
 return "What ever";
 }
}

$obj = Foo;

$str = (string) $obj; // вызывается __toString()

echo $obj; // вызывается __toString()
?>

К сожалению, на данный момент метод _toString работает только при использовании в контексте оператора echo/print.

Reflection API

PHP5 включает в себя reflection API, предоставляющий возможность реверс-инжиниринга классов, интерфейсов, функций, методов, а также расширений (extensions).

Reflection API также предоставляет доступ к doc-комментариям функций, классов и методов.

Практически все аспекты ОО-кода могут быть отражены с помощью reflection API. Reflaction API документируется отдельно.

Пример:

class Foo {
 public $prop;
 function Func($name) {
 echo "Hello $name";
 }
}

reflection_class::export('Foo');
reflection_object::export(new Foo);
reflection_method::export('Foo', 'func');
reflection_property::export('Foo', 'prop');
reflection_extension::export('standard');
?>

Новый диспетчер памяти

В PHP5 используется новый диспетчер памяти, более эффективно работающий в мультитрэдовой среде, так как он не использует мутексы (mutexes) для осуществления блокирования/разблокирования (lock/unlock) при операциях выделения/освобождения памяти (allocation/deallocation).




Рекомендуем почитать

 

Добавить комментарий


Ваше имя:


Комментарий:


Введите: Картинка