静态函数变量与静态 class 变量
static function variable vs static class variable
考虑以下几点:
class Super
{
static protected $class_var = 0;
public function __construct()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s\n", static::class, static::$class_var, $function_var);
}
public static function test()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s\n", static::class, static::$class_var, $function_var);
}
}
class A extends Super {}
class B extends Super {}
echo "Object calls\n";
new A();
new A();
new B();
echo "Class calls\n";
A::test();
A::test();
B::test();
PHP 7.2.7 输出:
Object calls
class_name : A, class_var : 1, function_var : 1
class_name : A, class_var : 2, function_var : 2
class_name : B, class_var : 3, function_var : 3
Class calls
class_name : A, class_var : 4, function_var : 1
class_name : A, class_var : 5, function_var : 2
class_name : B, class_var : 6, function_var : 1
为什么 A 和 B 在 class 上调用时有自己的静态函数 var。而 A 和 B 在调用实例时共享静态函数 var。或者更笼统地说,它们在内部究竟是如何工作的?
一般行为可以这样解释(下面有一个关于构造函数的附带条件):静态 class 属性的作用域是针对 class 的,其中它们是 定义的,静态方法变量的范围针对 class,它们被 调用 。
您的 test
方法被声明为静态的事实在这里并不重要,因此我将其缩减为以下测试脚本:
class Super
{
static protected $class_var = 0;
public function test()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s", static::class, static::$class_var, $function_var), PHP_EOL;
}
}
class A extends Super {}
class B extends Super {}
因为它在 class 上 定义 ,所以 $class_var
将始终链接到该范围。然而许多 classes 扩展 Super
,它们将引用同一个变量(除非它们覆盖它)。
另一方面,$function_var
的范围是 class(es),其中 test
方法被 调用 。对 A
的所有实例的调用将共享一个,对 B
的所有实例的调用将共享一个。
$a = new A;
$b = new B;
$a->test(); // class_name : A, class_var : 1, function_var : 1
$a->test(); // class_name : A, class_var : 2, function_var : 2
$b->test(); // class_name : B, class_var : 3, function_var : 1
构造函数(前提条件):
您问题中的另一个问题是构造函数的行为不同于任何其他 class 方法,因为尽管在语法上相似,但它根本不是一种方法。与 class 属性类似,在构造函数中声明为静态的任何变量的范围都在 class 范围内,其中它是 defined:
如果我们加入:
public function __construct()
{
static $constructor_var = 0;
$constructor_var++;
echo sprintf("class_name : %s, constructor_var : %s", static::class, $constructor_var), PHP_EOL;
}
那么我们可以演示如下:
$a = new A; // class_name : A, constructor_var : 1
$b = new B; // class_name : B, constructor_var : 2
除非任何子class重写构造函数,否则它们将共享同一个 $constructor_var
.
实例
不幸的是,我无法在文档中找到关于这些内容的任何一个很好的简单摘要,而且我也不确定其中有多少是设计使然的。构造函数中的静态变量尤其不是我认为我遇到过的东西,静态函数变量本身也越来越少见。但是知道事情是如何运作的很有趣,这是个好问题。
考虑以下几点:
class Super
{
static protected $class_var = 0;
public function __construct()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s\n", static::class, static::$class_var, $function_var);
}
public static function test()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s\n", static::class, static::$class_var, $function_var);
}
}
class A extends Super {}
class B extends Super {}
echo "Object calls\n";
new A();
new A();
new B();
echo "Class calls\n";
A::test();
A::test();
B::test();
PHP 7.2.7 输出:
Object calls
class_name : A, class_var : 1, function_var : 1
class_name : A, class_var : 2, function_var : 2
class_name : B, class_var : 3, function_var : 3
Class calls
class_name : A, class_var : 4, function_var : 1
class_name : A, class_var : 5, function_var : 2
class_name : B, class_var : 6, function_var : 1
为什么 A 和 B 在 class 上调用时有自己的静态函数 var。而 A 和 B 在调用实例时共享静态函数 var。或者更笼统地说,它们在内部究竟是如何工作的?
一般行为可以这样解释(下面有一个关于构造函数的附带条件):静态 class 属性的作用域是针对 class 的,其中它们是 定义的,静态方法变量的范围针对 class,它们被 调用 。
您的 test
方法被声明为静态的事实在这里并不重要,因此我将其缩减为以下测试脚本:
class Super
{
static protected $class_var = 0;
public function test()
{
static $function_var = 0;
static::$class_var++;
$function_var++;
echo sprintf("class_name : %s, class_var : %s, function_var : %s", static::class, static::$class_var, $function_var), PHP_EOL;
}
}
class A extends Super {}
class B extends Super {}
因为它在 class 上 定义 ,所以 $class_var
将始终链接到该范围。然而许多 classes 扩展 Super
,它们将引用同一个变量(除非它们覆盖它)。
$function_var
的范围是 class(es),其中 test
方法被 调用 。对 A
的所有实例的调用将共享一个,对 B
的所有实例的调用将共享一个。
$a = new A;
$b = new B;
$a->test(); // class_name : A, class_var : 1, function_var : 1
$a->test(); // class_name : A, class_var : 2, function_var : 2
$b->test(); // class_name : B, class_var : 3, function_var : 1
构造函数(前提条件):
您问题中的另一个问题是构造函数的行为不同于任何其他 class 方法,因为尽管在语法上相似,但它根本不是一种方法。与 class 属性类似,在构造函数中声明为静态的任何变量的范围都在 class 范围内,其中它是 defined:
如果我们加入:
public function __construct()
{
static $constructor_var = 0;
$constructor_var++;
echo sprintf("class_name : %s, constructor_var : %s", static::class, $constructor_var), PHP_EOL;
}
那么我们可以演示如下:
$a = new A; // class_name : A, constructor_var : 1
$b = new B; // class_name : B, constructor_var : 2
除非任何子class重写构造函数,否则它们将共享同一个 $constructor_var
.
不幸的是,我无法在文档中找到关于这些内容的任何一个很好的简单摘要,而且我也不确定其中有多少是设计使然的。构造函数中的静态变量尤其不是我认为我遇到过的东西,静态函数变量本身也越来越少见。但是知道事情是如何运作的很有趣,这是个好问题。