6.5. Клонирование
Объектная модель PHP 5 рассматривает объекты уникальным образом с использованием парадигмы неявной ссылки. В некоторых ситуациях может потребоваться репликация объекта, чтобы изменения, происходящие с репликой объекта, никак не отражались на самом оригинале. Для этой цели язык PHP позволяет создать специальный метод __clone. Как и в случае с методами __construct и __destruct, в начале имени этого метода используются два символа подчеркивания. Каждый объект
для метода_clone имеет стандартную реализацию. Стандартная реализация создает
новый объект, содержащий те же значения и ресурсы, что и оригинальный объект. Для того чтобы отменить стандартную реализацию метода в создаваемом вами классе, необходимо создать свою собственную версию метода __clone.
Метод clone не принимает аргументов, но работает с указателями на объект this и that, относящийся к реплицируемому объекту. При самостоятельной реализации метода __clone необходимо позаботиться о копировании любой информации, которую содержит ваш объект, из объекта that в объект this. При создании собственной реализации метода __clone процессор PHP не осуществляет неявное копирование значений.
В листинге 6.4 показан простейший способ присвоения объектам последовательных номеров.

Листинг 6.4. Метод_clone

<?php
class ObjectTracker
{
private static $nextSerial = 0;
private $id;
private $name;
function __construct($name)
$this->name = $name;
$this->id = ++self::$nextSerial;
function __clone()
$this->name = " Клон $that->name"; $this->id = ++self::$nextSerial;
function getId()
return($this->id); function getName()
return($this->name);
}}
$ot = new ObjectTracker("Объект Зеева"); $ot2 = $ot->__clone(); //1. объект Зеева
print($ot->getId() . " " . $ot->getName() . "<br>"); //2. клон объекта Зеева
print($ot2->getId() . " " . $ot2->getName() . "<br>");
?>

6.6. Свойства и методы доступа
Подобно любым другим переменным PHP, свойства экземпляра являются переменными. Для того чтобы сослаться на них, достаточно воспользоваться оператором ->. Символ доллара перед именем свойства указывать не нужно. В качестве примера сошлемся на строку листинга 6.1, в котором приведено свойство name объекта user.
Оператор -> может использоваться несколько раз. Если свойство объекта само содержит объект, то, для того чтобы получить доступ к свойству внутреннего объекта, можно использовать два оператора -> . Эти выражения можно даже задавать в строках, заключенных в двойные скобки. В листинге 6.5 показан пример объекта, который содержит массив объектов.
Методы доступа аналогичны свойствам доступа. Оператор -> используется для ссылки на метод экземпляра (см. пример вызова getLastLogin в листинге 6.1). Методы ведут себя так же как и функции, объявленные вне класса.
Если один класс распространяется на другой класс, свойства и методы всех порождающих классов имеются и в порожденном классе, даже несмотря на то, что он не был объявлен явным образом. Как было сказано выше, механизм наследования обладает очень большой мощностью. Если необходимо воспользоваться унаследованным свойством, достаточно сослаться на него, как если бы это было обычное локальное свойство. С другой стороны, с помощью оператора :: можно задать специальное пространство имен.

| Листинг 6.5. Объекты, включающие другие объекты
<?php
class Room
{
public $name;
function _construct($name="unnamed")
{
$this->name = $name;
}
}
class House
{
//массив комнат public $room;
}
// создать пустой дом $home = new house; // добавить комнаты
$home->room[] = new Room("bedroom"); $home->room[] = new Room("kitchen"); $home->room[] = new Room("bathroom"); //показать первую комнату в доме print($home->room[0]->name);
?> 
Язык PHP различает два специальных пространства имен в объектах. Пространство имен parent имеет отношение непосредственно к порождающему классу. Пространство имен self относится к текущему классу. В листинге 6.6 демонстрируется использование пространства имен parent для рекурсивного вызова порождающих конструкторов. Кроме того, в нем используется пространство имен self для вызова другого метода данного конструктора.

Листинг 6.6. Пространства имен parent и self

<?php
class Animal
{
public $blood;
public $name;
public function __construct($blood, $name=NULL)
{
$this->blood = $blood; if($name)
{
$this->name = $name;
}
}
}
class Mammal extends Animal
{
public $furColor; public $legs;
function __construct($furColor, $legs, $name=NULL)
{
parent::__construct("warm", $name); $this->furColor = $furColor; $this->legs = $legs;
}
}
class Dog extends Mammal
{
function __construct($furColor, $name)
{
parent::_construct($furColor, 4, $name);
self::bark();
}
function bark()
{
print("$this->name says 'woof!'");
}
}
$d = new Dog("Black and Tan", "Angus");

 В главе 4, "Функции", впервые упоминалась идея динамического вызова функций, где имя функции может быть представлено переменной. Аналогичная методика применима и к элементам объектов. Например, если необходимо определить имя свойства во время выполнения, можно записать выражение наподобие $this->$dynamicProperty. Аналогично, для вызова метода, заданного переменной method, можно воспользоваться выражением $obj->$method(1.23).
Кроме того, с помощью оператора -> можно воспользоваться значением, возвращаемым функцией, что было совершенно невозможно в предыдущих версиях PHP. Например, можно записать выражение вида $obj->getObject()->callMethod() , чтобы не создавать промежуточную переменную. Это также позволяет применять такой типовой проект разработки, как Factory.