Подтвердить что ты не робот

Что такое клонирование объектов в php?

Может кто-нибудь объяснить мне

  • Что такое клонирование объектов в php?

  • Когда я должен использовать ключевое слово clone в php?

4b9b3361

Ответ 1

Клонирование объектов - это акт создания копии объекта. Как отметил Коди, клонирование в 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 of User, но вы хотите иметь возможность предоставить им копию объекта Address. Приведенный выше пример иллюстрирует это. Метод getAddress возвращает клон объекта адреса вызывающим объектам. Это означает, что если вызывающий объект изменяет объект Address, внутренний адрес пользователя не изменится. Если вы не дали клон, то внешний объект мог бы иметь возможность изменять внутренний адрес пользователя, потому что ссылка задана по умолчанию, а не клоном.

Надеюсь, что все это имеет смысл.

PS:.
Имейте в виду, однако, что если Address также будет иметь внутренние объекты, вам нужно будет убедиться, что адрес делает глубокую копию себя при клонировании (как в моем втором примере этого сообщения), определяя __clone() в адресе. В противном случае у вас появятся головные боли, пытаясь понять, почему ваши данные завинчены.

Ответ 2

Клонирование используется для создания подлинной копии объекта. Присвоение объекта другой переменной не создает копию - скорее, она создает ссылку на ту же ячейку памяти, что и объект:

<?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"
}

Ответ 3

Клонирование объектов с точки зрения PHP 5 - это то, что известно как "мелкая копия" . Затем он вызывает метод __clone() для клонируемого объекта.

Ответ 4

Если вам нужен глубокий клон - то есть клоны дочерних объектов и клоны объектов внука - вы можете либо перезаписать __clone в каждом из классов, либо просто сериализовать + нестиализировать объект:

function deepClone($object)
{
    return unserialize(serialize($object));
}

Ответ 5

Как поясняется в других ответах, clone создает мелкую копию объекта.

Если вам нужно сделать глубокую копию (т.е. рекурсивную копию), вы можете перегрузить методы __clone().

Вы также можете использовать эту библиотеку: MyCLabs\DeepCopy, которая более простая и мощная, чем простой клон.