Другой задачей метода "__clone()" является управление клонированием сложного объекта, который имеет в своём составе другие объекты. Дело в том, что такие вложенные объекты не клонируются, для них просто создаётся псевдоним. Таким образом, несмотря на то, что создаются две независимые копии главного объекта, они по-прежнему указывают на один и тот же подобъект (см. рисунок).
Приведём пример, в котором создадим класс "ByClasses" который будет содержать в своём составе объект "subObject" класса "subClass".
class ByClasses {
public $subObject, $_work;
public function __construct() {
$this->subObject = new subClass();
$this->_work = 'Член класса - '. __CLASS__;
}
}
class subClass {
public $_work;
public function __construct() {
$this->_work = 'Член класса - '. __CLASS__;
}
}
$_Class_ByClasses = new ByClasses();
$_new_Class_ByClasses = clone $_Class_ByClasses;
$_new_Class_ByClasses->_work = 999;
$_new_Class_ByClasses->subObject->_work = 999;
echo $_Class_ByClasses->_work; # Результат: Член класса - ByClasses;
echo '<hr>';
echo $_Class_ByClasses->subObject->_work; # Результат: 999;
Следует отметить, что клонируется только непосредственные члены класса "ByClasses", внутренняя структура вложенного класса "subClass" не клонируется. Для того чтобы исправить такую ситуацию, объект "$subObject" необходимо клонировать явно в методе "__clone()".
Клонирование вложенного класса:
class subClass {
public $_work;
public function __construct() {
$this->_work = 'Член класса - '. __CLASS__;
}
}
class ByClasses {
public $subObject, $_work;
public function __construct() {
$this->subObject = new subClass();
$this->_work = 'Член класса - '. __CLASS__;
}
public function __clone() {
$this->subObject = clone $this->subObject;
}
}
$_Class_ByClasses = new ByClasses();
$_new_Class_ByClasses = clone $_Class_ByClasses;
$_new_Class_ByClasses->_work = 999;
$_new_Class_ByClasses->subObject->_work = 999;
// Клонируются все члены, в том числе и вложённых классов.
echo $_Class_ByClasses->_work; # Результат: Член класса - ByClasses;
echo '<hr>';
echo $_Class_ByClasses->subObject->_work; # Результат: Член класса - subClass;
Псевдоним вложенного объекта.