"@
lonesomeday,那似乎大部分是正确的。然而,特别是关于您的后续评论涉及继承的部分,函数内静态变量作用域的行为似乎更加复杂。我在所有示例中都使用PHP 5.3.16。
总结: 当在实例函数中使用static
关键字来定义变量时,其行为似乎会根据继承和函数调用堆栈中的位置而有所不同。
以下是一些示例。
首先,这类似于您的初始示例:在类的__construct()
方法中实例化一个静态变量,创建两个该类的实例,并查看该变量的行为。
"
<?php
class A {
public function __construct() {
static $i = 0;
$i++;
$this->i = $i;
}
}
$o1 = new A();
$o2 = new A();
printf("\$o1->i: %d\n", $o1->i);
printf("\$o2->i: %d\n", $o2->i);
?>
到目前为止,没有什么意外。该变量被实例化一次(为0),然后每个单独的实例都会递增。
如果您将类A扩展为B,并实例化其中一个(其他所有内容保持不变),则会得到相同的行为:
<?php
class A {
public function __construct() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i);
printf("\$o2->i: %d\n", $o2->i);
?>
再一次,没有惊喜。让我们回到第一个例子并稍微修改一下。首先,我们将静态变量的实例化/递增调用移动到成员方法中。请注意,我在这个例子中删除了类B。
<?php
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
$o1 = new A();
$o2 = new A();
printf("\$o1->i: %d\n", $o1->i);
printf("\$o2->i: %d\n", $o2->i);
?>
仍然是相同的输出。
然而,当你将
A
扩展为
B
,并保持相同的结构时:
<?php
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i);
printf("\$o2->i: %d\n", $o2->i);
?>
注意输出结果:在所有其他情况下,
$o2->i
变成了 2,除了这个情况。
因此,如果我们扩展
A
并将静态实例化移动到实例方法中,似乎我们现在引入了一个新的作用域来保存
$i
变量,而在所有其他情况下,实例共享该静态变量的作用域。
更令人困惑的是,考虑这个例子;它与前一个例子相同,但在这种情况下,类
B
得到了自己的
setI()
实现,它只是简单地调用其父类的实现。
<?php
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {
public function setI() {
parent::setI();
}
}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i);
printf("\$o2->i: %d\n", $o2->i);
?>
正如您所看到的,
$o2->i
现在又被设置为2了,这几乎是我们得到的所有结果(除了示例#4)。
对我来说,这似乎非常违反直觉。我希望不同的实例为该变量获取自己的作用域,或者所有实例(包括扩展类的实例)共享相同的作用域。
我无法确定这是否是PHP中的一个错误,还是预期行为。
PHP文档中关于静态变量作用域的说明说:
“静态变量仅存在于局部函数作用域中,但当程序执行离开此作用域时,它不会失去其值。”
他们没有详细说明在对象实例的上下文中如何定义“函数作用域”,因此我不确定示例#4中的边缘情况是否是预期的。
private static $template;
。 - NikiC