参考:https://blog.csdn.net/lamp_yang_3533/article/details/79912453
1.定义
后期静态绑定(也叫延迟静态绑定),可用于在继承范围内引用静态调用的类
2.工作原理
static 后期静态绑定的工作原理是存储了上一个非转发调用(non-forwarding call)的类名。
- 当进行静态方法调用时,该类名(static指向的类名)为明确指定的那个(通常是 :: 运算符的左侧部分),即实际调用时的类。
- 当进行非静态方法调用时,即为该对象所属的类。
- "后期绑定"的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。
3.转发调用
所谓的转发调用(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call() 。 可用 get_called_class() 函数被调用的方法所在的类名。
4.非转发调用
通过具体的类名或具体的对象进行的调用都是非转发调用,即非上面四种方式的调用都是非转发调用。
5.非静态环境下$this和static调用的区别
①$this 会优先寻找所在定义范围(父类)中的私有方法,如果存在就调用。 ②static 是先到它指向的类(子类)中寻找私有方法,如果找到了就会报错,因为私有方法只能在它所定义的类内部调用;如果没找到,再去所在定义范围(父类)中寻找该私有方法,如果存在就调用。
<?php class A { private function foo () { var_dump($this); echo '--'; var_dump(new static); echo '--'; echo __CLASS__; echo '--'; echo get_called_class(); echo '<br>'; } public function test () { $this -> foo (); static:: foo (); echo '<br>'; } } class B extends A { } class C extends A { private function foo () { echo 'this is C'; } } (new B())->test(); (new C())->test(); ?> //输出结果 object(B)#1 (0) { } --object(B)#2 (0) { } --A--B object(B)#1 (0) { } --object(B)#2 (0) { } --A--B object(C)#1 (0) { } --object(C)#2 (0) { } --A--C Fatal error: Uncaught Error: Call to private method C::foo() from context 'A' in /usercode/file.php:14 Stack trace: #0 /usercode/file.php(28): A->test() #1 {main} thrown in /usercode/file.php on line 14
6.后期静态绑定解析
后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。如果静态调用使用了 parent:: 或者 self:: 等转发调用的形式,将会转发调用信息。
<?php class A { public static function foo () { static:: who (); } public static function who () { echo __CLASS__ . " " ; } } class B extends A { public static function test () { A :: foo (); parent :: foo (); self :: foo (); static::foo(); forward_static_call(['A', 'foo']); echo '<br>'; } public static function who () { echo __CLASS__ . " " ; } } class C extends B { public static function who () { echo __CLASS__ . " " ; } public static function test2() { self::test(); } } class D extends C { public static function who () { echo __CLASS__ . " " ; } } B::foo(); B::test(); C::foo(); C::test(); D::foo(); D::test2(); ?> //输出结果 B A B B B B C A C C C C D A D D D D