Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Estou tentando entender o comportamento que encontrei ao clonar objetos de um tipo, vou explicar melhor.
Uma vez que clone é utilizado para clonar objetos, e não apenas a sua referência, eu utilizo muito para "poupar" algumas linhas de código. Como no exemplo abaixo:
$data1= clone $data2 = new DateTime();
$data1->add(new DateInterval('PT5M'));
$data2->add(new DateInterval('PT10M'));
echo '<pre>';
var_dump($data1 , $data2);
echo '</pre>';A saída é normal como esperado:
>
object(DateTime)#2 (3) {
["date"]=>
string(19) "2013-09-02 13:46:50"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
object(DateTime)#1 (3) {
["date"]=>
string(19) "2013-09-02 13:51:50"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
Objetos diferentes e independentes (instância #1 e #2).
Entretanto, encontrei uma peculiaridade ao se clonar um objeto do tipo ArrayIterator. Realizando o mesmo processo:
$list1 = clone $list2 = new ArrayIterator();
$list2->append('primeiro valor');
$list1->append('segundo valor');
echo '<pre>';
var_dump($list1 , $list2);
echo '</pre>';Saída:
>
object(ArrayIterator)#2 (1) {
["storage":"ArrayIterator":private]=>
array(2) {
[0]=>
string(14) "primeiro valor"
[1]=>
string(13) "segundo valor"
}
}
object(ArrayIterator)#1 (1) {
["storage":"ArrayIterator":private]=>
array(2) {
[0]=>
string(14) "primeiro valor"
[1]=>
string(13) "segundo valor"
}
}
Apesar de serem objetos diferentes (instâncias #1 e #2) ambos possuem a referência ao mesmo storage.
Como podem ver no código em funcionamento no link abaixo:
http://codepad.viper-7.com/LaBQpt
Eu encontrei esse bug foi reportado para a versão PHP 5.1
https://bugs.php.net/bug.php?id=36941 (considerada corrigida)
E novamente reportado para a versão 5.2
https://bugs.php.net/bug.php?id=50000
Também encontrei alguns referências que diziam que não era um bug e sim uma peculiaridade devido a flag implementada, por default, pelo ArrayIterator. Mas nada que resolvesse ou explicasse como obter o comportamento desejado.
Agora a questão, esse é o comportamento correto ou realmente um bug? Já que, segundo este exemplo, com um array (tipo primitivo), funciona como o esperado.
Uma idéia que me ocorre aqui... Já tentou estender a classe ArrayIterator, implementar um __clone e usar a sua classe no lugar da nativa?
No link do bug (#50000) o usuário tentou fazer isso. É algo específico da referência do storage do ArrayIterator.
O que me leva a crer que, se eu preciso utilizar um storage diferente, não há necessidade me usar ArrayIterator.
Edit---
Pensei que ele tinha feito isso.
Vou fazer uns testes aqui.
Edit 2--
O meu problema não é nem solução para isso, só queria realmente saber se é um bug.
Não sou especialista em clonagem de objetos mas, pela que se vê no manual da ArrayIterator não existe um método __clone, o que me leva a imaginar que a keyword clone apenas segue o curso natural dela sem, de fato, clonar o objeto.
Uma idéia que me ocorre aqui... Já tentou estender a classe ArrayIterator, implementar um __clone e usar a sua classe no lugar da nativa?