这将是一个很难解释的问题。
我有一个相当复杂的类Tree,我试图简化:
class Tree {
/**
* @var Node[]
*/
private $nodes;
/**
* @var Edge[]
*/
private $edges;
}
class Node {
/**
* @var Value[]
*/
private $values;
/**
* @var array
*/
private $someArray;
}
class Value {
/**
* @var float
*/
private $result;
}
因此,您可以看到,我有一个对象树,其中再次包含两个对象数组(节点和边)并且每个节点都有一个对象数组(值)有一个属性结果。
为了计算属性结果,我基本上需要在树上来回运行等等……所以有些人有业务逻辑,最终会在同一个树中,但我的节点有一些计算结果。
到目前为止,我所做的是:
$tree = myCalculationFunction($tree, $calcParameter);
return $tree->getNode(1)->getValue(1)->getResult();
但是没有,当我用不同的calcParameter额外调用相同的函数时,当然我的树在引用的节点、值等上操作。
所以我不能:
$initialTree = myCalculationFunction($tree, $calcParameter);
$treeOne = myCalculationFunction($initialTree, $calcParameterOne);
$treeTwo = myCalculationFunction($initialTree, $calcParameterTwo);
$result1 = $treeOne->getNode(1)->getValue(1)->getResult();
$result2 = $treeTwo->getNode(1)->getValue(1)->getResult();
所以到目前为止,我还没有$initialTree的深层副本,因为其中的所有对象都是byReference。我无法克隆,也看不出像这里这样的手动/自定义深度复制将如何适用于这种情况。
我如何在这里实现这一点?我基本上需要initialTree是稳定的,并且每个计算函数调用都操纵最初"计算树"的完整副本。
您可以扩展这个问题的方法,并为每个类实现一个自定义的__clone
方法。由于节点或边本身之间似乎没有任何关系,因此应该足以实现您想要的。
值得一提的是,正如文档中所描述的,__clone
在克隆后立即在新对象上调用。它实际上并不负责克隆对象,这在一开始可能看起来是合乎逻辑的。
因此,简化为Tree
和Node
类:
class Tree
{
private $nodes;
private $edges;
public function __clone()
{
$this->nodes = array_map(function ($node) {
return clone $node;
}, $this->nodes);
$this->edges = array_map(function ($edge) {
return clone $edge;
}, $this->edges);
// clone other properties as necessary
}
}
class Node
{
private $values;
private $someArray;
public function __clone()
{
$this->values = array_map(function ($value) {
return clone $value;
}, $this->values);
$this->someArray = array_map(function ($elem) {
return clone $elem;
}, $this->someArray);
// clone other properties as necessary
}
}
只需为以后的每个类遵循这个模式,它就会递归地深度克隆整个树。