#7. 9 php ООП Копирование объектов: clone, __clone()
Primary tabs
Копирование объектов
При выполнении строки
$lion = new Animal;
в переменной $lion
сохраняется ссылка на объект класса Animal
. Если присвоить переменную $lion
какой-то другой переменной:
$lion2 = $lion
новый объект не будет создан, а лишь продублирована ссылка на уже существующий. Если нам нужно создать новый объект, который будет являться копией существуещего, необходимо использовать ключевое слово clone
:
<?php $lion = new Animal; $lion2 = clone $lion;
Теперь $lion
и $lion2
— это два разных объекта.
Переопределение операции копирования
По умолчанию операция clone
выполняет побитовое копирование всех свойств объекта. В некоторых случаях это может быть не тем, что требуется. Например, если объект сам хранит ссылки на другие объекты, то, возможно, эти данные должны быть скопированы с помощью того же ключевого слова clone
. Рассмотрим пример:
class Animal { private $name; private $children = []; } $lion = new Animal;
Свойство $children
соответствует списку детей животного, каждый из которых является объектом этого же класса Animal
. При выполнении копирования с помощью clone
$lion2 = clone $lion;
для объекта, на который ссылается переменная $lion
, будет создана его копия. Однако, если список children
объекта $lion
не пуст, то новый объект $lion2
будет хранить в своем свойстве children
ссылки на те же самые объекты. Если нам это не подходит, то в классе должен быть описан специальный метод __clone
, который вызывается всякий раз при использовании ключевого слова clone
по отношению к объекту этого класса.
Пример 1. Переопределение операции копирования объектов
<?php <?php class Animal { private $name; private $children = []; public function __construct($text) { $this->name = $text; } public function set_name($text) { $this->name = $text; } public function add_child($child) { $this->children[] = $child; } public function get_children() { return $this->children; } public function print_children() { foreach ($this->children as $value) { echo $value->name, " "; } } public function __clone() { foreach ($this->children as $key => $value) { $this->children[$key] = clone $value; } } } $lion = new Animal("Бонифаций"); $lion->add_child(new Animal("Симба")); $lion2 = clone $lion; $child2 = $lion2->get_children()[0]; $child2->set_name("Другой Симба"); $lion->print_children(); echo "<BR>"; $lion2->print_children();
В данном примере мы создаём объект с именем "Бонифаций" и добавляем ему одного ребенка — объект с именем "Симба":
$lion = new Animal("Бонифаций"); $lion->add_child(new Animal("Симба"));
Затем копируем объект "Бонифаций" с помощью ключевого слова clone
:
$lion2 = clone $lion;
в результате чего вызывается описанный в классе специальный метод __clone
. В момент вызова __clone
уже выполнено побитовое копирование свойства $children
объекта $lion
в $this
нового объекта. В методе выполняется обход массива $this->children
нового объекта и перезапись каждого элемента этого массива (каждый элемент заменяется его копией, сделанной с помощью clone
):
foreach ($this->children as $key => $value) { $this->children[$key] = clone $value; }
После завершения копирования мы меняем имя ребенка объекта $lion2
и убеждаемся в том, что имя ребенка $lion
при этом не изменилось.
Результатом выполнения примера будут строки:
Симба
Другой Симба
Запрет клонирования
Если объявить метод __clone
с модификатором доступа private:
class Animal { private $name; private function __clone() { } }
то в программе нельзя будет сделать копию объекта никакими способами. Этот подход применяется, если объект должен существовать в программе в единственном экземпляре.
- Log in to post comments
- 312 reads