PHP OOP继承:子类同名静态变量为何存在两个不同值?
问题原因
PHP中self关键字属于编译时硬绑定,永远指向定义当前方法的类,不会随调用类的变化动态匹配,这是代码里静态属性值不一致的核心原因:
dbEntity类中setConnection、getConnection方法里的self::$connection,始终操作的是父类dbEntity自身的静态属性,和子类Patient里重写的同名静态属性完全是两个独立变量。- 执行
$p->setConnection("myConnection")时,修改的是父类的$connection值,子类Patient自带的$connection = "patientConnection"根本没被改动,所以直接读Patient::$connection和调用方法拿到的结果不一样。 - 额外注意:父类里
$name属性用private修饰,子类无法继承重写这个属性,就算调整绑定关键字也读不到子类定义的$name值。
修复方案
使用PHP提供的延迟静态绑定特性,把方法里所有绑定静态属性的self关键字替换成static即可。static会在运行时动态绑定到实际调用方法的类,能正确识别子类重写的静态属性。
另外如果需要子类重写父类静态属性,要把父类对应属性的访问修饰符从private改成protected(允许子类继承重写)。
修正后的可运行代码:
<?php Class dbEntity { protected static $connection; // 访问修饰符从private改为protected,允许子类重写 protected static $name = "dbEntity"; public static function getName() { // self替换为static return static::$name; } public static function setConnection($connection) { // self替换为static static::$connection = $connection; } public static function getConnection() { // self替换为static return static::$connection; } } Class Patient extends dbEntity { public static $connection = "patientConnection"; public static $name = "Patient"; } $p = new Patient(); $p->setConnection("myConnection"); echo $p->getConnection() . "\n"; // 输出:myConnection echo Patient::$connection . "\n"; // 输出:myConnection echo $p->getName() . "\n"; // 输出:Patient
补充说明
- 延迟静态绑定从PHP 5.3.0版本开始正式支持,专门解决继承场景下静态成员的调用绑定问题。
- 静态属性的存储是按类隔离的,没有绑定关键字做桥接的话,父类和子类的同名静态属性是完全独立的存储空间,不会互相覆盖。
内容的提问来源于stack exchange,提问作者Alpha_B
相关产品推荐
相关产品推荐

