Php 非静态方法中的静态在实例之间共享

Php 非静态方法中的静态在实例之间共享,php,Php,我遇到了一些意外的行为,对象方法中定义的静态变量在实例之间共享。这可能是已知的行为,但当我浏览PHP文档时,在对象方法中找不到静态定义变量的实例 以下是我遇到的行为的简化: <?php class Foo { public function dofoo() { static $i = 0; echo $i++ . '<br>'; } } $f = new Foo; $g = new Foo; $f->dofoo(); // expected

我遇到了一些意外的行为,对象方法中定义的静态变量在实例之间共享。这可能是已知的行为,但当我浏览PHP文档时,在对象方法中找不到静态定义变量的实例

以下是我遇到的行为的简化:

<?php

class Foo {
  public function dofoo() {
    static $i = 0;
    echo $i++ . '<br>';
  }
}

$f = new Foo;
$g = new Foo;

$f->dofoo(); // expected 0, got 0
$f->dofoo(); // expected 1, got 1
$f->dofoo(); // expected 2, got 2

$g->dofoo(); // expected 0, got 3
$g->dofoo(); // expected 1, got 4
$g->dofoo(); // expected 2, got 5
这是静态的

如果希望成员特定于对象的实例,则可以使用

e、 g


这就是static,它在类的所有实例中都是相同的变量

class Foo {
  private $i = 0;
  public function dofoo() {
    echo $this->i++ . '<br>';
  }
}
您希望编写此代码,使变量成为类实例的私有成员

class Foo {
  private $i = 0;
  public function dofoo() {
    echo $this->i++ . '<br>';
  }
}
class-Foo{
私人$i=0;
公共函数dofoo(){
echo$this->i++.
; } }
静态关键字可以使用,也可以使用。静态变量是在PHP4中引入的(我想,它可能更早)。PHP5中引入了静态类成员/方法

因此,根据手册,一个静态变量

变量作用域的另一个重要特征是静态 变量静态变量仅存在于局部函数中 作用域,但在程序执行时它不会丢失其值 离开这个范围


这与你描述的行为一致。如果需要每个实例变量,请使用常规类成员

我同意当前的PHP文档对于非静态方法中静态变量的“作用域”的确切含义不够清楚

当然,正如hobodave所指出的,“静态”通常意味着“每个类”,但静态类属性与(非静态)方法中的静态变量并不完全相同,因为后者由方法“限定范围”(类中的每个方法都可以有自己的静态$foo变量,但最多可以有一个名为$foo的静态类成员)

我认为,尽管PHP5的行为是一致的(“静态”总是意味着“每个类一个共享实例”),但这并不是PHP的唯一行为方式


例如,大多数人使用静态函数变量在函数调用中保持状态,而对于全局函数,PHP行为正是大多数人所期望的。因此,可以想象一个PHP解释器在方法调用中维护某些方法变量的状态,并且“每个实例”都这样做,这实际上也是我第一次声明局部方法变量为静态时所期望的情况。

Ups 7年了,时间很长,但不管怎样,还是这样

所有的类都有一个默认构造函数,我为什么这么说?!? 因为如果在构造函数中定义默认行为,则类的每个实例都将受到影响

例如:

namespace Statics;

class Foo
{
    protected static $_count;

    public function Bar()
    {
        return self::$_count++;
    }

    public function __construct()
    {
        self::$_count = 0;
    }
}
namespace Statics;

class Foo
{
    //default value
    protected static $_count = 0;

    public function Bar()
    {
        return self::$_count++;
    }

    public function __construct()
    {
       //do something else
    }
}
导致:

require 'Foo.php';

use Statics\Foo;

$bar = new Foo();
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';

$barcode = new Foo();
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';

0
1
2
0
1
2
require 'Foo.php';

use Statics\Foo;

$bar = new Foo();
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';

$barcode = new Foo();
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';

0
1
2
3
4
5
导致:

require 'Foo.php';

use Statics\Foo;

$bar = new Foo();
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';

$barcode = new Foo();
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';

0
1
2
0
1
2
require 'Foo.php';

use Statics\Foo;

$bar = new Foo();
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';
echo $bar->bar().'<br>';

$barcode = new Foo();
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';
echo $barcode->bar().'<br>';

0
1
2
3
4
5
需要'Foo.php';
使用Statics\Foo;
$bar=新的Foo();
echo$bar->bar()。
; echo$bar->bar()。
; echo$bar->bar()。
; $barcode=新的Foo(); echo$barcode->bar()。
; echo$barcode->bar()。
; echo$barcode->bar()。
; 0 1. 2. 3. 4. 5.
正如您所看到的,结果是完全不同的,类实例之间的内存空间分配是相同的,但它可以根据您定义默认值的方式产生不同的结果

我希望这有帮助,不是因为上面的答案是错误的,而是我觉得从这个角度理解all概念很重要


来自葡萄牙的尊敬!

文档是针对静态类属性和方法的,而不是方法中的静态变量。亚当:在PHP5中,它们是一个相同的。静态是静态的。在我看来,
$f->dofoo()
$g->dofoo()不同。显然,PHP开发人员的想法不一样。:)你是对的,它们不一样,但它们都作用于同一个变量,因为您将其标记为静态。感谢Dave,这与我所寻找的更为接近:静态引用(在某种程度上)绑定到代码行,而不是执行期间定义的任何实例。