深拷贝带有对象数组属性的对象 - 如何实现或者有其他解决方案?

15 浏览
0 Comments

深拷贝带有对象数组属性的对象 - 如何实现或者有其他解决方案?

这将是一个难以解释的问题。

我有一个相当复杂的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;
}

所以你可以看到我有一个包含两个对象数组(Node和Edge)的Tree对象,每个Node都有一个对象数组(Value),还有一些其他的简单数组,每个Value都有一个result属性。

为了计算result属性,我基本上需要在我的树中上下运行等等...所以有些业务逻辑最终会在仍然是相同的Tree中生成一些计算出的节点结果。

到目前为止,我所做的是这样的:

$tree = myCalculationFunction($tree, $calcParameter);
return $tree->getNode(1)->getValue(1)->getResult();

但是当我使用不同的calcParameter调用同样的函数时,我的Tree操作的是引用的Nodes、Values等。

所以我不能这样做:

$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的深拷贝,因为其中的所有对象都是按引用的。我不能克隆,也不知道如何对这种情况进行手动/自定义的深拷贝,类似于这里(链接)的方法。

我应该如何在这里实现?我基本上需要initialTree保持稳定,每个计算函数调用都操作最初“计算出的树”的完全副本。

0
0 Comments

问题出现的原因是需要对包含数组属性的对象进行深拷贝。原始的拷贝方法只能进行浅拷贝,即只拷贝对象的引用而不是对象本身。为了解决这个问题,可以通过实现自定义的__clone方法来进行深拷贝。

具体的解决方法如下:

1. 在TreeNode类中实现__clone方法。

2. 在__clone方法中,使用array_map函数对数组属性进行遍历并进行深拷贝。

3. 根据需要,对其他属性进行类似的处理。

以上是对Node类的__clone方法的示例代码:

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
}

按照这种模式,对每个类进行类似的处理,可以递归地进行整个树的深拷贝操作。

另外,还可以使用第三方库DeepCopy来实现深拷贝。这个库遵循了上述方法的原理,但是需要在项目中增加依赖。

通过实现__clone方法,可以对包含数组属性的对象进行深拷贝。另外,还可以使用第三方库DeepCopy来简化这个过程。

0