我一直认为static
变量只被初始化一次并保留它们的值直到脚本结束。但是我在我的代码中遇到了一个错误,其中通过增加静态变量中的计数器来创建div
ID属性。
这是错误的复制品:
class Node {
var $child = array();
public function test () {
static $var = 0;
$var++;
echo $var,"\n";
foreach ( $this->child as $c )
$c->test();
}
public function add_child ( $c ) {
$this->child[] = $c;
}
}
class Tree extends Node {
public function __construct() {
parent::add_child( new Node() );
parent::add_child( new Node() );
}
}
$tree = new Tree();
$tree->test();
上面有3次调用test()
,其中预期输出应为
1 2 3
但是,变量static $var
正在初始化两次,产生输出:
1 1 2
有人可以解释为什么会这样吗?
答案 0 :(得分:2)
看起来$var
和孩子Tree::test()
正在调用静态变量Node::test()
。不确定解决这个问题的最佳方法。但我所做的是让Tree::add_child()
添加类Tree
的子对象而不是类Node
。
class Node {
var $child = array();
public function test () {
static $var = 0;
$var++;
echo $var,"\n";
foreach ( $this->child as $c )
$c->test();
}
public function add_child ( $c ) {
$this->child[] = $c;
}
}
class Tree extends Node {
public static function createInitial() {
$tree = new Tree();
$tree->addChild();
$tree->addChild();
return $tree;
}
public function addChild() {
parent::add_child( new Tree() );
}
}
$tree = Tree::createInitial();
$tree->test();
答案 1 :(得分:1)
这是一些讨厌的代码。当您遇到这样的问题时,最好退后一步,考虑另一种方式。否则,当您在6个月内回来添加新功能时,您需要使用键盘面板。
在黑暗中拍摄,看起来像Late Static Binding(lsb)在这里工作。您实例化的$ tree对象创建了两个节点对象,每个节点对象都有一个test()方法,每个方法都绑定了static $var
。
$ var值
$tree->test() $tree->child[0]->test() $tree->child[1]->test()
1 1 2
请注意,$tree->child[1]->test()
调用输出2,这是因为static $var
变量将自身绑定到$tree
对象,当您创建初始$tree->test()
时,该对象已经递增调用
我在原始代码中添加了一些输出来证明这一点:
class Node {
public $id;
var $child = array();
public function test () {
static $var = 0;
$var++;
var_dump(sprintf('Id: %d | Var: %d', $this->id, $var));
foreach ( $this->child as $key => $c ) {
var_dump(sprintf('Container Object Id: %d | Child Id: %d | Var: %d', $this->id, $c->id, $var));
$c->test();
}
}
public function add_child ( $c ) {
$this->child[] = $c;
}
}
class Tree extends Node {
public function __construct() {
$node1 = new Node;
$node1->id = 1;
$node2 = new Node;
$node2->id = 2;
parent::add_child( $node1 );
parent::add_child( $node2 );
}
}
$tree = new Tree;
$tree->test();
// Output
// Conclusion: $var bound itself to $tree during runtime
string 'Id: 0 | Var: 1' (length=14)
string 'Container Object Id: 0 | Child Id: 1 | Var: 1' (length=45)
string 'Id: 1 | Var: 1' (length=14)
string 'Container Object Id: 0 | Child Id: 2 | Var: 1' (length=45)
string 'Id: 2 | Var: 2' (length=14)