什么是php中的对象克隆?

什么是php中的对象克隆?,php,object,clone,Php,Object,Clone,有人能给我解释一下吗 什么是php中的对象克隆 什么时候应该在php中使用clone关键字 对象克隆,在PHP5中,是一种被称为。然后对被克隆的对象调用_clone()方法。克隆用于创建对象的真实副本。将一个对象分配给另一个变量不会创建一个副本,相反,它会创建一个与该对象相同的内存位置的引用: <?php $o= new stdclass; $o->a= 'b'; $o->b= 'c'; $o2= $o; $o2->a= 'd'; var_dump($o); va

有人能给我解释一下吗

  • 什么是php中的对象克隆

  • 什么时候应该在php中使用clone关键字


对象克隆,在PHP5中,是一种被称为。然后对被克隆的对象调用_clone()方法。

克隆用于创建对象的真实副本。将一个对象分配给另一个变量不会创建一个副本,相反,它会创建一个与该对象相同的内存位置的引用:

<?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);

?>

对象克隆是复制对象的行为。如前所述,PHP中的克隆是通过创建对象的浅拷贝来完成的。这意味着克隆对象的内部对象将不会被克隆,除非您通过定义魔术方法
\uu clone()
明确指示对象也克隆这些内部对象

如果不使用
\uu 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;
例如,克隆的用例是您不希望外部对象与对象的内部状态混淆的情况

假设您有一个具有内部对象地址的类用户

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;
    }
}
为了参数起见,假设您不希望外部对象弄乱用户对象的内部地址,但您确实希望能够为它们提供地址对象的副本。上面的例子说明了这一点。
getAddress
方法将地址对象的克隆返回给调用对象。这意味着,如果调用对象更改Address对象,则用户的内部地址不会更改。如果您没有提供克隆,那么外部对象将能够更改用户的内部地址,因为默认情况下提供的是引用,而不是克隆

希望这一切都有意义

PS.:

不过要注意,如果Address也有内部对象,则必须通过在Address中定义
\uu clone()
来确保Address在克隆时对自身进行深度复制(如本文的第二个示例所示)。否则,您将很难弄清楚数据被破坏的原因。

如果您需要深度克隆(即子对象的克隆和孙对象的克隆),您可以覆盖每个类中的
\u clone
,或者简单地序列化+取消序列化对象:

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

如其他答案所述,
clone
对对象进行浅拷贝

如果需要进行深度复制(即递归复制),可以重载
\u clone()
方法


您也可以使用此库:,它比简单的克隆更简单、更强大。

但是为什么要克隆它而不是执行
$o2=new stdClass修改属性,如
$o2->a='d'是否给出了相同的结果?@samayo:不,它也给出了
$o3->b=$o->b
。请记住,leepowers编写了一个简单的示例,但是在更复杂的场景中,使用相同类型的对象复制所有属性(这些属性随后可以在不修改原始对象的情况下重新分配)的好处是巨大的。这是一个很好的解决方法。你为我节省了数小时的编码时间,谢谢!
function deepClone($object)
{
    return unserialize(serialize($object));
}