2013-02-16 48 views
1

我想知道如何克隆包含對象的擴展類SplHeap。例如,如果FooHeap擴展了SplHeap,FooHeap是否有可能擁有__clone方法並克隆它的對象元素?克隆SplHeap,其中包含PHP中的對象

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

    public function __clone(){ 

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

或者,如果我必須創建一個新的FooHeap對象和重新插入對象元素的克隆中,有一種方法(例如,從頂部到底部,或從底部到頂部),我應該重新 - 插入克隆的元素以確保優化性能?

+1

這聽起來像你想堆的深層副本(參見淺拷貝,其中堆積對象每個堆中都是一樣的)。是對的嗎? – salathe 2013-02-16 10:38:10

+0

是的,我想要一個堆的深層副本。有什麼辦法可以解決這個問題嗎? – Wee 2013-02-16 10:42:37

+0

我可能只是遍歷堆(在'__clone()'內部),臨時存儲克隆對象的某處('SplObjectStorage','SplFixedArray'等)。一旦完成第一個循環,堆將是空的,此時您可以遍歷臨時存儲和'insert()'克隆的對象。 – salathe 2013-02-16 11:06:41

回答

2

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) { 
} 
0

通過定義函數__clone,您可以指定要爲克隆對象更改哪些變量。在下一個例子中,我將$克隆爲true。原始對象有$clone = false,但克隆的對象有$cloned = true。因此$數據保持不變。

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

?> 
+0

但是,如何訪問存儲在SplHeap中的數據節點? – Wee 2013-02-16 09:59:41

+0

更新了我的答案。 – vikingmaster 2013-02-16 10:24:25