You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP延迟静态绑定中static::与$this调用私有方法的疑问

PHP私有方法与继承的方法调用疑问

测试代码

class ParentClass
{
    private function first(): void
    {
        p(__METHOD__);
    }

    public function test(): void
    {
        static::first();

        $this->first();

        $B = new B();
        $B->first();
    }
}

class B extends ParentClass
{
    public function first(): void
    {
        p(__METHOD__);
    }
}

$B = new B();
$B->test();

执行输出

B::first

ParentClass::first

ParentClass::first

疑问

为何当$this指向B类实例,且B类的first()方法为public访问修饰符时,调用的却是ParentClass中的私有first()方法?而移除ParentClass中first()的private修饰符允许继承后,就会调用B类的first()方法?

这看起来是否不符合逻辑?原本预期至少直接调用时会执行B::first(),难道是因为B类的first()并未重写ParentClass的first()方法,而是仅同名,所以在ParentClass作用域中无法被识别?即只有重写而非仅同名的方法,才能在父类作用域中被调用?

解答

核心原因是PHP的私有方法无法被子类重写,子类中同名的first()只是一个全新的独立方法,和父类的私有first()没有任何继承关联。

  1. 关于static::first():
    static是后期静态绑定,会指向当前运行时的实际类(也就是B类),所以调用的是B类定义的first(),这就是第一个输出B::first的原因。

  2. 关于$this->first():
    虽然$this指向的是B类实例,但这段代码是在ParentClass的test()方法作用域内执行的。对于私有方法,PHP采用编译时绑定——在解析ParentClass代码阶段,就已经确定$this->first()调用的是ParentClass自身的私有first(),完全不会去子类中查找同名方法。因为私有方法不允许被继承,子类的同名方法对父类来说是“不可见”的。

  3. 关于$B->first():
    同样是在ParentClass的作用域内调用,由于父类的first()是私有,PHP会直接判定你要调用的是父类自己的私有方法,不会触发子类同名方法的执行。只有当父类方法为public/protected时,才会触发运行时多态,调用子类重写后的方法。

当你将ParentClass的first()改为public/protected后,子类的first()才是真正的重写,此时无论是static::还是$this->调用,都会遵循多态规则执行子类的方法。

内容的提问来源于stack exchange,提问作者Max Denusenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:07:23