2013-02-16 2 views
1

Мне хотелось бы знать, как я могу клонировать расширенный класс SplHeap, который содержит объекты. Например, если FooHeap расширяет SplHeap, возможно ли, чтобы FooHeap имел метод __clone и клонировал его элементы объекта?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

+0

да, я хочу глубокую копию кучи. Есть ли способ получить это? – Wee

+0

Я бы, наверное, просто переместил кучу (внутри '__clone()'), временно сохранив клонированные объекты где-нибудь ('SplObjectStorage',' SplFixedArray' и т. Д.). Как только этот первый цикл будет завершен, куча будет пустой, после чего вы можете перебрать временное хранилище и «вставить()» клонированные объекты. – salathe

ответ

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, вы можете указать, какие переменные вы хотите изменить для клонированного объекта. В следующем примере я устанавливаю $ 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 

?> 
+0

Но как я могу получить доступ к узлам данных, хранящимся в SplHeap? – Wee

+0

Обновлен мой ответ. – vikingmaster