Рассмотрим разницу между присваиванием одного объекта другому и клонированием объекта.
class testClass {
public $property;
}
$a = new testClass;
$a->property = 'Значение';
# $b и $a ссылаются на один и тот же объект (ссылка)
$b = $a;
# Изменит свойство и для $a, т.к. это один и тот же объект
$b->property = 'Новое значение';
# $c - клон $a, но теперь это разные объекты
$c = clone $a;
# Не влияет на $a или $b
$c->property = 'Еще одно значение';
# Изменения, сделанные через $b, отразятся на $a, но не на $c, так как $c является отдельным клоном объекта
# Выведет "Новое значение"
echo $a->property;
# Выведет "Новое значение", так как $b - это тот же объект, что и $a
echo $b->property;
# Выведет "Еще одно значение", так как $c - это отдельный объект
echo $c->property;
В примере создаём объект класса testClass и затем присваиваем его другим переменным $b и $c, но для $c используем ключевое слово clone. Ключевые отличия между $b и $c:
1. Присваивание ($b = $a)
При простом присваивании $b = $a, переменная $b становится ссылкой на тот же самый объект, что и $a. Это значит, что обе переменные $a и $b ссылаются на один и тот же объект в памяти. Изменения, сделанные через любую из этих переменных, отразятся на объекте, на который они обе ссылаются.
2. Клонирование ($c = clone $a)
Когда клонируем объект с помощью clone $a, создаётся новый объект, который является копией $a. Переменная $c ссылается на этот новый объект, который имеет те же свойства, что и исходный объект $a, но является отдельным экземпляром. Изменения, сделанные через $c, не повлияют на исходный объект $a и наоборот.
Клонирование объекта в PHP — это поверхностное клонирование
Поверхностное клонирование в PHP означает, что при клонировании объекта создаётся новый экземпляр класса, и все примитивные типы данных (такие как int, string, bool) копируются из оригинала в клон. Однако, если в объекте есть свойства, которые сами являются объектами, то в клоне эти свойства будут ссылаться на те же объекты, что и в оригинальном объекте. Это может вызвать непредвиденное поведение, если вы изменяете эти вложенные объекты, ожидая, что изменения коснутся только одного из экземпляров (оригинала или клона).
Для реализации глубокого клонирования, когда необходимо, чтобы все вложенные объекты также были скопированы, вам нужно определить поведение клонирования в магическом методе __clone.
В этом примере, при клонировании объекта MyObject, мы явно указываем, что хотим также клонировать вложенный объект SubObject. Благодаря этому, у нас получается два полностью независимых объекта: изменения, сделанные в клоне, не затронут оригинальный объект и наоборот. Это и есть глубокое клонирование.
class SubObject {
public $value;
public function __construct($value) {
$this->value = $value;
}
}
class MyObject {
# Свойство, которые само является объектом
public $subObject;
public function __construct() {
$this->subObject = new SubObject("original");
}
public function __clone() {
# Создаем новый экземпляр SubObject для клона
$this->subObject = clone $this->subObject;
}
}
# Создаем объект MyObject
$original = new MyObject();
$clone = clone $original;
# Изменяем свойство subObject в клоне
$clone->subObject->value = "cloned";
# Выведет "original"
echo $original->subObject->value;
# Выведет "cloned"
echo $clone->subObject->value;
Комментарии
0Нашли ошибку или хотите дополнить материал?