OOP 最大函数嵌套级别


OOP maximum function nesting level

>我对OOP有一个奇怪的情况

我的课程很简单

class Thing{
  private
    $children = array(),
    $parent;

  public function addChild(self $thing){
    $this->children[] = $thing;
    $thing->setParent($this);
  }
  public function setParent(self $thing){
    $this->parent = $thing;
    $thing->addChild($this);
  }
}

$a = new Thing();
$b = new Thing();
$b->setParent($a);

如果我尝试使用这些函数,我会得到最大函数嵌套级别为 100 的错误,我知道为什么,但是我应该如何更改代码?现在的方式是有道理的,但是如果我删除任何函数调用,它将无法正常工作。

如注释中所述,您的代码在 setParent()addChild() 之间创建了一个无限循环,其中对 setParent() 的调用隐式调用 setChild() ,而 又再次调用 setParent()

如果您希望代码正常工作,以便对setParent()的调用addChild()的调用强制执行两个对象中属性中的关系,则可以通过在addChild()中添加if ()条件来解决当前遇到的无限循环,仅当对象的父对象还不是当前对象($this(时才调用setParent()

同样,您需要使用 in_array() 检查要添加为 addChild() 中的子对象是否尚未添加到父级的 $children 数组中。

class Thing{
  private
    $children = array(),
    $parent;
  // A name property just to see the results
  public $name;

  public function addChild(self $thing){
    $this->children[] = $thing;
    // Only set this object to the passed-in $thing object's
    // $parent property if it has not already been set:
    if ($thing->parent !== $this) {
      $thing->setParent($this);
    }   
  }
  public function setParent(self $thing){
    $this->parent = $thing;
    // Only add the child via addChild() if it is not
    // already in the array
    if (!in_array($this, $thing->children)) {
      $thing->addChild($this);
    }
  }
}
$a = new Thing();
$a->name = "THING A";
$b = new Thing();
$b->name = "THING B";
// Specify $a as the parent of $b
$b->setParent($a);
echo "'$a properties:'n";
print_r($a);
echo "'$b properties:'n";
print_r($b);

上面的输出是:

$a properties:
Thing Object
(
    [children:Thing:private] => Array
        (
            [0] => Thing Object
                (
                    [children:Thing:private] => Array
                        (
                        )
                    [parent:Thing:private] => Thing Object
 *RECURSION*
                    [name] => THING B
                )
        )
    [parent:Thing:private] => 
    [name] => THING A
)
$b properties:
Thing Object
(
    [children:Thing:private] => Array
        (
        )
    [parent:Thing:private] => Thing Object
        (
            [children:Thing:private] => Array
                (
                    [0] => Thing Object
 *RECURSION*
                )
            [parent:Thing:private] => 
            [name] => THING A
        )
    [name] => THING B
)

现在,使用反向操作,从 $a$b 开始,然后将$b作为子项添加到$a,而不是将$a添加为$b的父项:

$a = new Thing();
$a->name = "THING A";
$b = new Thing();
$b->name = "THING B";
// Add $b as a child of $a
$a->addChild($b);

生成相同的输出:

$a properties:
Thing Object
(
    [children:Thing:private] => Array
        (
            [0] => Thing Object
                (
                    [children:Thing:private] => Array
                        (
                        )
                    [parent:Thing:private] => Thing Object
 *RECURSION*
                    [name] => THING B
                )
        )
    [parent:Thing:private] => 
    [name] => THING A
)
$b properties:
Thing Object
(
    [children:Thing:private] => Array
        (
        )
    [parent:Thing:private] => Thing Object
        (
            [children:Thing:private] => Array
                (
                    [0] => Thing Object
 *RECURSION*
                )
            [parent:Thing:private] => 
            [name] => THING A
        )
    [name] => THING B
)

(关于print_r()输出中的"递归"的说明:这并不表示方法调用的行为是递归的,只是对象引用之间存在递归关系,这是您想要的。 $a有一个子$bprint_r()尝试显示$b的父级,这指向$a