【问题标题】:Clone SplHeap that contains Objects in PHP在 PHP 中克隆包含对象的 SplHeap
【发布时间】:2013-02-01 06:13:36
【问题描述】:

我想知道如何克隆一个包含对象的扩展类 SplHeap。例如,如果 FooHeap 扩展了 SplHeap,那么 FooHeap 是否可以有一个 __clone 方法并克隆它的对象元素?

class FooHeap extends SplHeap{
    public function compare($value1, $value2){.... }

    public function __clone(){

        // how do I access its elements to clone?
    }
}

或者,如果我必须创建一个新的 FooHeap 对象并重新插入对象元素的克隆,有没有一种方法(例如从上到下,或从下到上)我应该重新插入克隆的确保优化性能的元素?

【问题讨论】:

  • 听起来您想要堆的深层副本(参见浅层副本,其中堆的对象在每个堆中都是一个且相同的)。对吗?
  • 是的,我想要堆的深层副本。有什么办法可以得到吗?
  • 我可能只是在堆上循环(在__clone() 内),将克隆的对象临时存储在某处(SplObjectStorageSplFixedArray 等)。一旦第一个循环完成,堆将是空的,此时你可以循环临时存储和insert()克隆的对象。

标签: php clone spl


【解决方案1】:

SplHeap 的本质是它自动对所有插入的值(如对象)进行排序,并在对其进行迭代时,从堆中删除每个值。

当您克隆堆时,插入的值也会被复制,但对象不会被克隆,而是按预期复制为引用。

通常的方法是遍历存储的数据并克隆找到的每个对象。但是因为迭代会删除节点,所以你必须在某个地方收集它们并重新插入。

没有选择的顺序,因为你所能做的就是“得到下一个”。

如果您确实担心性能,请测量!

我发现这段代码可以正常工作:

class MyHeap extends SplHeap
{

    public function compare($a, $b)
    {
        return (strcmp(get_class($a), get_class($b)));
    }

    public function __clone()
    {
        echo "Im cloning in ";
        foreach ($this as $obj) {
            $clones[] = clone($obj);
        }
        foreach ($clones as $obj) {
            $this->insert($obj);
        }
        var_dump($this);
    }
}

$heap = new MyHeap();

$obj1 = new stdClass();
$heap->insert($obj1);
$obj2 = new stdClass();
$heap->insert($obj2);

var_dump($heap);

$clone = clone($heap);

var_dump($clone);
foreach ($clone as $insert) {
    var_dump($insert);
}
foreach ($heap as $insert) {
    var_dump($insert);
}

输出:

class MyHeap#1 (0) {
}
Im cloning in class MyHeap#4 (0) {
}
class MyHeap#4 (0) {
}
class stdClass#6 (0) {
}
class stdClass#7 (0) {
}
class stdClass#2 (0) {
}
class stdClass#3 (0) {
}

【讨论】:

    【解决方案2】:

    通过定义函数__clone,您可以指定要为克隆对象更改哪些变量。在下一个示例中,我将 $cloned 设置为 true。原始对象具有$clone = false,但克隆对象具有$cloned = true。因此 $data 保持不变。

    <?php
    
    class FooHeap extends SplHeap {
        public $data = "asd"  ;
        private $cloned = false ;
    
        public function __clone(){
              $this->cloned = true ;
            $this->rewind() ; //Just rewind iterator back to start, if you need
        }
    
        public function compare(){
    
        }
    }
    
    $original = new FooHeap() ;
    $original->insert("some stuff") ;
    $original->insert(100) ;
    
    $clone = clone $original  ; //Data nodes are cloned from original object
    
    $data = array() ;
    $length = $clone->count() ;
    
    for ($i = 0 ; $i < $length ; $i++){
        $data[] = $clone->current() ; //Access current data node and store it in data
        $clone->next() ;                // Move to the next data node
    }
    
    var_dump($data) ; //Check your data array
    
    ?>
    

    【讨论】:

    • 但是如何访问存储在 SplHeap 中的数据节点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2014-11-20
    相关资源
    最近更新 更多