PHP中self::是否存在延迟绑定的特殊情况?
关于PHP延迟绑定中
self::行为的疑问 PHP官方文档中关于延迟绑定(late static binding)的说明指出:
self::会解析为编写该代码所在的类,例如在CurrentClass类中编写self::test(),等效于CurrentClass::test()。
但执行以下与文档示例类似的PHP代码:
<?php class A { // 返回延迟绑定的类名 public static function meth(): string { return static::class; } } class B extends A { public function check(): void { // 分别调用A、B、C的meth方法 echo "A: ".A::meth()."\n"; echo "B: ".B::meth()."\n"; echo "C: ".C::meth()."\n"; // 预期调用B的meth方法,输出B echo "self: ".self::meth()."\n"; // 预期调用运行时类的meth方法,输出C echo "static: ".static::meth()."\n"; // 预期调用B的meth方法,输出B echo "__CLASS__: ".(__CLASS__)::meth()."\n"; echo "selfclass: ".(self::class)::meth()."\n"; // 预期调用运行时类的meth方法,输出C echo "staticclass: ".(static::class)::meth()."\n"; } } // C继承B,未重写check方法 class C extends B {} (new C)->check();
在PHP 8.1.2中运行后输出:
A: A B: B C: C self: C static: C __CLASS__: B selfclass: B staticclass: C
其中self: C的输出不符合预期——按照文档描述,self::meth()应该等效于B::meth(),输出B,但实际输出了C。这是Bug、特殊特性,还是对文档的理解有误?
解答
这不是Bug,是对self::和延迟绑定的理解偏差:
self::确实指向定义该代码的类(这里是B),但self::meth()并没有调用B类自己的meth方法——因为B没有重写meth,这个方法是从A继承来的。- A类的
meth方法返回的是static::class,这里的static::是延迟绑定标记,它的指向取决于运行时的调用上下文:当通过C的实例调用check方法时,整个调用的运行时类是C,所以A中static::class最终指向C,导致输出C。
再对比其他几个调用的差异:
(__CLASS__)::meth()和self::class::meth():__CLASS__和self::class都是字符串"B",相当于显式调用B::meth(),此时A中static::class的上下文是B,所以输出B。static::meth():static::直接指向运行时类C,调用后A中static::class自然指向C,输出C。
内容的提问来源于stack exchange,提问作者Džuris
相关产品推荐
相关产品推荐

