PHP中static关键字_静态属性和方法的继承规则【解答】
PHP中,子类未重定义静态属性/方法时与父类共享内存;self::绑定定义类,static::绑定调用类(后期静态绑定);privatestatic成员子类不可访问;子类显式重写静态属性后形成独立副本。
PHP中静态属性和方法的“继承”机制,和很多人直觉中的“复制一份”完全不是一回事。说白了,子类如果没有显式声明自己的同名静态成员,那它和父类共享的是同一个内存地址。而self::与static::的行为差异,更是区分新手与老手的关键分水岭。至于private static,那就更直接了——子类根本碰都碰不到。
static属性在子类未重定义时是共享的
假设父类定义了一个 public static $count = 0,而子类A和B都没有声明自己的 $count。那么当你执行 A::$count = 5 之后,B::$count 和 Parent::$count 无一例外都会变成5。这不是bug,这是PHP有意为之的设计。
- 所有未重写的子类,访问的都是父类那个内存地址上的值;
- 哪怕只是通过
new A()创建实例,再执行A::$count++,也会波及整个继承链; - 这种共享特性在单例模式、计数器、配置缓存等场景中,极易引发意想不到的副作用。
self:: 和 static:: 在继承中行为完全不同
self:: 绑定到**方法定义所在的类**,而 static:: 则绑定到**实际调用时的类**(即后期静态绑定,LSB)。理解这一点,才算真正抓住了静态继承的行为本质。
- 在父类方法中写
return self::$value,无论子类是否重写了$value,永远拿回父类的值; - 写
return static::$value,子类如果重写了$value,就会返回子类的值,没重写则回退到父类; - 一旦子类显式重写了
$value(比如protected static $value = 'child'),那它就和父类断开共享,变成一个独立副本。
private static 成员不会被继承
private static 是严格意义上的私有成员,子类根本无法访问,更谈不上“继承”。尝试在子类中用 self:: 或 parent:: 访问父类的 private static 属性,会直接引发 Fatal error: Uncaught Error: Cannot access private property。
protected static可被子类访问,也能被static::解析到(前提是子类没有重写);public static最开放,但也要格外小心跨子类误改;- 一句话:不存在“继承 private 成员”这回事,只有“不可见”。
static方法的继承表现取决于调用方式
当子类没有重写 public static function foo() 时,Child::foo() 实际执行的就是父类中的那段代码。此时 $this 不可用,self:: 始终指向父类,而 static:: 指向 Child。
- 若方法内部使用了
self::$x,结果永远来自父类,和调用者无关; - 若使用了
static::$x,且子类重写了$x,则会取子类的值;没重写则取父类; - 子类重写该方法后,
self::和static::都指向子类(因为方法定义已经移到子类)。
最容易忽略的一点:静态属性是否被“真正继承”,完全取决于子类有没有那一行 public static $xxx 声明。没有声明,就是共享;有声明,才是隔离。别靠直觉,直接看代码里有没有那行字。



































