Полный цикл в digital

Копирование объектов класса

При присваивании объекта класса другой переменной создается новая ссылка на тот же объект:

<?
class Person {
public $name;
function __construct($name) {
$this->name = $name; 
}
}
$tom = new Person("Tom");
$bob = $tom;
$bob->name = "Bob";
echo $tom->name; // Bob

В данном случае после присваивания $bob = $tom; обе переменных будут указывать на один и тот же объект. Поэтому если мы поменяем свойство $name у одной переменной, то это измение затронет и другую переменую. Так как они ссылаются на один и тот же объект.

Однако такое поведение может быть нежелательным, если мы хотим, чтобы после копирования переменные представляли независимые друг от друга объекты. И для этого PHP предоставляет оператор clone:

<?
class Person {
public $name;
function __construct($name){
$this->name = $name;
}
}
$tom = new Person("Tom");
$bob = clone $tom; // копируем объект из $tom в переменную $bob
$bob->name = "Bob";
echo $tom->name; // Tom

При применении оператора clone все свойства, которые представляют примитивные типы и массивы, копируются в новый объект. Однако, что если у нас свойство класса представляет другой класс:

<?
class Company {
public $name;
function __construct($name) { 
$this->name = $name; 
}
}
class Person {
public $name, $company;
function __construct($name, $company) {
$this->name = $name;
$this->company = $company;
}
}
$microsoft = new Company("Microsoft");
$tom = new Person("Tom", $microsoft);
$bob = clone $tom; // копируем объект из $tom в переменную $bob
$bob->name = "Bob";
$bob->company->name = "Google"; // изменяем у Боба название компании
$bob->languages[0] = "french";
echo $tom->company->name; // Google - у Тома тоже изменилась компания

Здесь в принципе мы сталкиваемся с той же ситуацией, что и в первом примере. Класс Person содержит свойство, которое представляет класс Company. При клонировании объекта:

$bob = clone $tom;

Обе переменных $tom и $bob будут содержать ссылку на один и тот же объект Company. Соответственно если через одну переменную изменить свойства этого объекта:

$bob->company->name = "Google";

то изменение затронет и другую переменную:

echo $tom->company->name; // Google

Чтобы выйти из этой ситуации, необходимо в классе определить метод __clone. Он вызывается при клонировании и может применяться для клонирования вложенных объектов:

<?
class Company {
public $name;
function __construct($name) { 
$this->name = $name; 
}
}
class Person {
public $name, $company;
function __construct($name, $company) {
$this->name = $name;
$this->company = $company;
}
function __clone() {
$this->company = clone $this->company;
}
}
$microsoft = new Company("Microsoft");
$tom = new Person("Tom", $microsoft);
$bob = clone $tom; // копируем объект из $tom в переменную $bob
$bob->name = "Bob";
$bob->company->name = "Google"; // изменяем у Боба название компании
$bob->languages[0] = "french";
echo $tom->company->name; // Microsoft - у Тома НЕ изменилась компания
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг