我自己注意到类实例中静态属性的异常行为,有一段代码:
class A{
public static $key=0;
public function getKey(){
return self::$key;
}
}
class B extends A {}
A::$key = 1;
$b = new B();
echo $b->getKey();
到这里一切都清楚了,我们改变了类的静态属性 A::$key = 1; 从客户端。之后,类 A 的任何实例或此类的继承者(在本例中为 B)的静态属性 $ key 的值都会发生变化
但是下面的代码让我变得无法理解——在下面的代码中,我们更改了类实例的静态属性,这自动影响了类的静态属性。这是什么 ?- 这个类的所有继承人中的某个全局变量?这是代码
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
$a = new A();
echo $a->getKey().'</br>';
$a->plus();
echo $a->getKey().'</br>';
$b = new B();
echo $b->getKey().'</br>';
发出
0
1
1
这是另一个代码
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
$a = new A();
echo $a->getKey().'</br>';
$b = new B();
$a->plus();
echo $a->getKey().'</br>';
echo $b->getKey().'</br>';
发出
0
1
1
结果,任何继承人中静态属性的任何更改都会自动更改所有实例中的静态属性 - 继承人。好吧,这是全局变量的替代方法,或者我不明白某些东西,并且出于某种原因他们没有在教科书中写到它。
基于@perfect words
设置一个实验
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
class C extends A {}
$b = new B();
$c = new C();
$b->plus();
echo $c->getKey().'</br>';
发出
1
因此,它们具有全局可见性——无论类实例位于何处
但这还不是全部,正如@chernomyrdin 在引用同一个静态变量时的实践所示——您可以访问 RAM 的不同部分。这样一来,不同的值可以存储在同一个变量中
<?php
class A {
protected static $key=0;
public function getGlobalKey(){
return self::$key;
}
//применяем позднее статическое связывание
public function getCurrentKey(){
return static::$key;
}
public function plusGlobalKey(){
++self::$key;
}
//применяем позднее статическое связывание
public function plusCurrentKey(){
++static::$key;
}
}
class B extends A{
protected static $key=0;
}
class C extends B{}
$a = new A();
$a->plusGlobalKey();
$b = new B();
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
$a->plusGlobalKey();
echo '<hr/>';
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
$b->plusCurrentKey();
echo '<hr/>';
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
echo '<hr/>';
$c = new C();
echo $c->getCurrentKey().'<br/>';
echo $c->getGlobalKey().'<br/>';
显示
1
0
1
-----------------
2
0
2
-----------------
2
1
2
-----------------
1
2
总结:@perfect - 解释了为什么会这样
@chernomyrdin - 推到后期静态绑定的主题 - 在最后一个例子中,我只是理解它是如何工作的
重要的是要理解
общие
类的所有实例的静态属性都存在于единичном
表单中(类本身存储此类字段)。静态属性类的任何实例的每次更改都会反映在所有其他实例中。在你的例子中,你执行了一次 $a->plus() 函数;从头开始,您在这两种情况下都得到了一个单元。
为了让大家能够充分理解,我画了一张图来说明内存中存储统计变量的原理。
静态变量的范围受类本身限制以防止外部更改(与全局变量不同)并且仅供此类的后代使用(例如,交换任何信息)
对于 PHP 中的静态,一切都很复杂,首先是它们的访问方式
self::$key
,static::$key
而且 5.x 和 7.0 中的行为也不同那么这里有一个例子来思考:
工作结果: