<?phpclass A { ???public static function foo() { ???????static::who(); ???} ???public static function who() { ???????echo __CLASS__."\n"; ???}}class B extends A { ???public static function test() { ???????/*A::foo(); ???????A::foo(); ???????B::foo();*/ ???????A::foo(); ???????parent::foo(); ???????self::foo(); ???} ???public static function foo() { ???????static::who(); ???} ???public static function who() { ???????echo __CLASS__."\n"; ???}}// 当有parent和self前缀时,可以考虑换成具体的类名进行思考// 如果函数的内容是static前缀,则要考虑最后一次“非转发调用”的类名// 当有parent和self前缀时,如此例,只需要考虑调用这个函数的类就可以了,在这里是C::test()class C extends B {public static function test() { ???????A::foo(); ???????parent::foo(); ???????self::foo(); ???} ??public static function foo() { ???????static::who(); ???} ???public static function who() { ???????echo __CLASS__."\n"; ???}}C::test();// A C C
- 转发调用: 进行静态调用时前面有static修饰的
- 非转发调用: 直接通过类名,方法名调用的
- 后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)中的类名
- 意思是当我们调用一个转发调用的静态调用时,实际调用的类是上一个非转发调用的类。
- 分析一下上面的例子
- Class C的test方法中的三个方法,它们的非转发调用类都是C,因为它是直接通过C::test()方式访问的
- A::foo() 非转发调用 方法内部又进行了转发调用,这时的上一个非转发调用的类是A,所以输出A
- parent::foo() 调用了Class B的foo方法,该方法内进行了一次转发调用,这时的上一个非转发调用的类是C,所以输出C
- self::foo() 调用了自身的foo方法,该方法内也进行了一次转发调用,道理同上,所以输出C
- 可以尝试将Class C foo方法中的static::who()分别替换成self::who(), parent:who() 看看效果,前者输出C 后者输出B
PHP中的后期静态绑定
原文地址:https://www.cnblogs.com/wjf0/p/8111491.html