这将是一个难以解释的问题。
我有一个相当复杂的类树,我试着简化:
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;
}
所以你可以看到我有一个对象树包含两个对象数组(节点和边缘),每个节点都有一个< strong>对象数组(值),其他一些“简单数组”和每个值都有属性结果。
要计算属性结果,我基本上需要在我的树上运行等...所以有些业务逻辑最终仍然在同一个树中,但我的节点有一些计算结果。
所以我到目前为止做的是:
$tree = myCalculationFunction($tree, $calcParameter);
return $tree->getNode(1)->getValue(1)->getResult();
但是当我使用不同的calcParameter另外调用相同的函数时,当然我的Tree操作引用的节点,值等。
所以我不能:
$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。我无法克隆,我也看不到像here这样的手动/自定义深层复制如何适用于此案例。
我怎样才能实现这一目标?我基本上需要initialTree稳定,每个计算函数调用都会操作最初“计算树”的完整副本。
答案 0 :(得分:3)
您可以从this问题扩展该方法,并为每个类实现自定义__clone
方法。由于节点或边缘本身之间似乎没有任何关系,因此应该足以完成您想要的任务。
值得一提的是,正如documentation中所述,在克隆后立即在新对象上调用__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
}
}
只需按照此模式为每个课程进行操作,它将以递归方式深度克隆整个树。