Клонирование объекта - это процесс создания копии объекта. Как указывало Коди , клонирование в 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 с внутренним объектом Address.
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. Приведенный выше пример иллюстрирует это. Метод getAddress
возвращает клон объекта адреса вызывающим объектам. Это означает, что если вызывающий объект изменяет объект адреса, внутренний адрес пользователя не изменится. Если вы не предоставили клон, то внешний объект сможет изменить внутренний адрес пользователя, поскольку по умолчанию дается ссылка, а не клон.
Надеюсь, все это имеет какой-то смысл.
PS:.
Имейте в виду, однако, что если у Address также есть внутренние объекты, вам нужно убедиться, что Address делает полную копию себя при клонировании (согласно моему второму примеру этого поста), определив __clone()
в Address. В противном случае вы получите головную боль, пытаясь выяснить, почему ваши данные облажались.