Может кто-нибудь объяснить мне
что такое клонирование объектов в php?
Когда я должен использовать ключевое слово clone в php?
Может кто-нибудь объяснить мне
что такое клонирование объектов в php?
Когда я должен использовать ключевое слово clone в php?
Клонирование объекта — это процесс создания копии объекта. Как указал Cody, клонирование в PHP выполняется путем создания неглубокая копия объекта. Это означает, что внутренние объекты клонированного объекта не будут клонированы, если только вы явно не укажете объекту клонировать и эти внутренние объекты, определив магический метод __clone()
.
Если вы не используете метод __clone
, внутренние объекты нового объекта будут ссылками на те же объекты в памяти, что и внутренние объекты исходного объекта, который был клонирован.
Рассмотрим эти примеры:
// in this exampe the internal member $_internalObject of both objects
// reference the same instance of stdClass in memory.
class CloneableClass
{
private $_internalObject;
public function __construct()
{
// instantiate the internal member
$this->_internalObject = new stdClass();
}
}
$classA = new CloneableClass();
$classB = clone $classA;
// in this exampe the internal member $_internalObject of both objects
// DON'T reference the same instance of stdClass in memory, but are inividual instances
class CloneableClass
{
private $_internalObject;
public function __construct()
{
// instantiate the internal member
$this->_internalObject = new stdClass();
}
// on clone, make a deep copy of this object by cloning internal member;
public function __clone()
{
$this->_internalObject = clone $this->_internalObject;
}
}
$classA = new CloneableClass();
$classB = clone $classA;
Случаи использования для клонирования, например, были бы случаем, когда вы не хотите, чтобы внешние объекты связывались с внутренним состоянием объекта.
Допустим, у вас есть класс User с внутренним адресом объекта.
class Address
{
private $_street;
private $_streetIndex;
private $_city;
// etc...
public function __construct( $street, $streetIndex, $city /* etc.. */ )
{
/* assign to internal values */
}
}
class User
{
// will hold instance of Address
private $_address;
public function __construct()
{
$this->_address = new Address( 'somestreet', '1', 'somecity' /* etc */ );
}
public function getAddress()
{
return clone $this->_address;
}
}
В качестве аргументов предположим, что вы не хотите, чтобы внешние объекты связывались с внутренними объектами Address объектов User, но вы хотите иметь возможность предоставить им копию объекта Address. Приведенный выше пример иллюстрирует это. Метод getAddress
возвращает вызывающим объектам клон объекта адреса. Это означает, что если вызывающий объект изменит объект Address, внутренний адрес пользователя не изменится. Если вы не предоставили клон, то внешний объект смог бы изменить внутренний адрес пользователя, потому что по умолчанию дается ссылка, а не клон.
Надеюсь, все это имеет какой-то смысл.
PS.
Имейте в виду, однако, что если Address также будет иметь внутренние объекты, вам нужно будет убедиться, что Address делает глубокую копию себя при клонировании (согласно моему второму примеру этого поста). ), определив __clone()
в Address. В противном случае вы получите головную боль, пытаясь понять, почему ваши данные облажались.
Клонирование используется для создания подлинной копии объекта. Присвоение объекта другой переменной не создает копию, а создает ссылку на ту же ячейку памяти, что и объект:
<?php
$o= new stdclass;
$o->a= 'b';
$o->b= 'c';
$o2= $o;
$o2->a= 'd';
var_dump($o);
var_dump($o2);
$o3= clone $o;
$o3->a= 'e';
var_dump($o);
var_dump($o3);
?>
Этот пример кода выведет следующее:
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#2 (2) {
["a"]=>
string(1) "e"
["b"]=>
string(1) "c"
}
$o2= new stdClass;
, изменение свойств, таких как $o2->a= 'd';
, дает тот же результат, верно?
- person samayo; 27.01.2014
$o3->b = $o->b
. Имейте в виду, что leepowers написал простой пример, но преимущество того же типа объекта со всеми скопированными свойствами, которые впоследствии можно переназначить без изменения исходного объекта, огромно в более сложных сценариях.
- person Samuel Kirschner; 23.02.2017
Клонирование объектов в PHP 5 называется "мелкой копией". . Затем он вызывает метод __clone() для клонируемого объекта.
Если вам нужен глубокий клон, то есть клоны дочерних объектов и клоны внучатых объектов, вы можете либо перезаписать __clone
в каждом из классов, либо просто сериализовать+несериализовать объект:
function deepClone($object)
{
return unserialize(serialize($object));
}
Как объяснялось в других ответах, clone
создает неглубокую копию объекта.
Если вам нужно сделать глубокую копию (т. е. рекурсивную копию), вы можете перегрузить методы __clone()
.
Вы также можете использовать эту библиотеку: MyCLabs\DeepCopy, которая более проста и мощнее простого клона.