PHP中抽象类构造函数获取子类属性值的原因及术语咨询
为什么PHP父类构造函数中会获取到子类的属性值?
首先先纠正下你代码里的两个小问题:parent是PHP的保留关键字,不能用作类名;子类名chile应该是child的笔误吧?不过这不影响核心问题的解释,我先把修正后的可运行代码贴出来:
abstract class ParentClass { protected $test = ['parent']; public function __construct() { die(var_dump($this->test)); } } class ChildClass extends ParentClass { protected $test = ['child']; } new ChildClass(); // 实际输出: array(1) { [0]=> string(5) "child" }
核心原因与对应的PHP术语
这个现象的本质是属性覆盖(Property Overriding),再结合PHP中$this关键字的上下文特性导致的:
- 属性覆盖的本质:当子类定义了和父类同名的非静态属性时,子类的属性会隐藏父类的同名属性。这里的关键是,子类的属性并不是“替换”了父类的属性,而是在子类的实例中,同名属性的优先级更高。
$this的上下文:在PHP中,$this始终指向当前正在操作的对象实例——哪怕是在父类的方法里。当你实例化ChildClass时,整个对象的本质是子类实例,只是继承了父类的方法。所以当父类构造函数执行$this->test时,它访问的是子类实例中已经初始化好的$test属性(也就是['child'])。
执行流程拆解
当你调用new ChildClass()时,PHP的执行顺序是这样的:
- 第一步:初始化子类
ChildClass的实例,此时子类的$test属性会被先赋值为['child']。 - 第二步:因为子类没有定义自己的构造函数,PHP会自动调用父类的构造函数。
- 第三步:父类构造函数中的
$this指向的是已经初始化好的子类实例,所以访问$this->test时,自然拿到的是子类的属性值。
如何让父类构造函数获取自己的属性值?
如果想让父类构造函数访问自己的$test,不受子类覆盖的影响,可以把父类的属性设置为private:
abstract class ParentClass { private $test = ['parent']; // 改为private public function __construct() { die(var_dump($this->test)); // 此时输出['parent'] } } class ChildClass extends ParentClass { protected $test = ['child']; // 这是子类独立的属性,和父类的$test互不干扰 } new ChildClass();
因为private属性只能在定义它的类内部访问,子类无法覆盖这个属性,只能定义自己的同名属性(两者是完全独立的),所以父类构造函数中访问的就是自己的$test了。
内容的提问来源于stack exchange,提问作者Elegance accessory
相关产品推荐
相关产品推荐

