PHP如何检测无限递归?

时间:2012-11-10 22:41:41

标签: php recursion

  

可能重复:
  How does PHP avoid infinite recursion here?

有人在Twitter上将其发布为php #wtf:

class A
{
    private $b;

    function __construct()
    {
        unset($this->b);
    }

    function __get($n)
    {
        echo '!broken!';
        return $this->$n;
    }
}

$a = new A;
$a->b; //EDIT: original question had var_dump($a->b);

//output:
!broken!!broken!

我对此的第一反应是$ a-> b触发第一个回声的__get(),然后返回$ this-> $ n触发__get再次导致$ this-> b仍然不存在,可能是__get()中包含的代码应该处理。 PHP自动检测无限递归并在那里停止。这是有道理的,但另一方面,PHP仅为欠定义属性A :: $ b提供E_NOTICE错误。

所以我的问题是,我是否正确PHP自动检测无限递归?我怎么能说出来?还是有其他理由来解释给出的输出?

1 个答案:

答案 0 :(得分:0)

在类中,不隐藏私有变量。因此,在执行下面的代码时,您可以获得变量$ b,而无需调用__get():

class A {
  private $b;
  function get_b()
  {
      return $this->b;    
      }
 }

$a = new A; 
echo $a->get_b();

但在下面一个,你不能 - 它会调用函数__get():

class A 
{
    private $b;
    function get_b()
    {
        return $this->b;    
        }

}

 $a = new A; echo $a->b;

所以在你的例子中:

  

A级{       私人$ b;

function __construct()
{
    unset($this->b);
}

function __get($n)
{
    echo '!broken!';
    return $this->$n;
} 
}
$a = new A; // Here you called unset, and since it doesn't know the "b", it calls __get().
var_dump($a->b); // Again here $a->b is not "exists" or "hidden", so it calls __get() again. 

在__get()中,“return $ this-> $ n”确实知道变量$ n - 也就是说$ b(就像我的第一个代码示例 - 函数get_b())。所以它实际上不是无限递归,它就像任何其他函数调用一样;)