PHP和对象成员函数中的静态变量


PHP and Static Variables in Object Member Functions

直到今天,我认为我已经很好地掌握了静态修饰符的工作原理。我知道(用外行的话来说)函数中的静态变量不会在调用该函数时"重置",而且我知道类中的静态变量和函数可以通过类本身(而不是类的实例化)调用它们来访问。

我的问题是:今天我发现如果我在类的非静态函数的内部声明了一个静态变量,那么该类的所有实例化在对成员函数的单独调用中共享该静态变量。

例如:

class A {
    public function GetValue() {
        static $value = 0;
        $value++;
        return $value;
    }
}
$instance_1 = new A();
$instance_2 = new A();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
echo $instance_2->GetValue();
echo $instance_2->GetValue();
echo $instance_1->GetValue();
echo $instance_1->GetValue();

注意,GetValue函数既没有被声明为静态的,也没有以静态的方式使用(比如,在类本身上调用)。

现在,我一直假设这将输出:121234

相反,我发现它将输出:123456

就像我说的,如果静态变量$value在静态函数内部,我会理解这一点。然而,由于它在非静态函数中,我只是假设它只会"绑定"到每个单独实例化中的函数。

我想我的问题是双重的,那么……1)这是一个错误还是预期的行为?2)其他语言是否以同样的方式对待这些"静态中的非静态"变量,或者这是PHP独有的?
  1. 在c++中也是如此(也可能是其他语言)。

你应该把非静态类成员函数看作是普通函数,只不过有一个由解释器自动提供的隐式$this参数。(这正是它们在大多数语言中实现的方式。)

我从Josh Duck的文章中复制了以下信息:http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/

静态变量从PHP 4开始就可用了,它允许您定义一个只能从当前函数访问的持久变量。这允许您将状态封装到函数或方法中,并且可以消除对类的需求,而单个函数就足够了。

当静态变量在类方法中定义时,它们将始终引用调用该方法的类。在这样做时,它们的行为几乎就像通过静态引用的属性一样,尽管存在细微的差异。

静态变量不能保留调用类的作用域。如果您的继承方法包含静态变量,且该静态变量可从其类的内部和外部调用,则可能会出现潜在的问题。

据我所知,所有带有静态变量的语言都是这样对待它们的。静态变量可以看作是全局变量,只能在特定范围内访问。