-
博文分类专栏
- Jquery基础教程
-
- 文章:(15)篇
- 阅读:46563
- shell命令
-
- 文章:(42)篇
- 阅读:154236
- Git教程
-
- 文章:(36)篇
- 阅读:234848
- leetCode刷题
-
- 文章:(76)篇
- 阅读:131789
-
PHP后期静态绑定之static-parent-self2017-08-19 10:15 阅读(6639) 评论(3)
概念
关于静态绑定,手册上是这么说的:
自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。
该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
首先看一个实例,你能全部正确的答出来吗?
<?php class A { public static function foo() { static::who(); } public static function who() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } } class B extends A { public static function test() { self::who(); //self指的是当前类B,但调用者仍然是C,self只是起到转发调用者的作用,相当于C调用了B的who方法 parent::who(); //parent指的是当前类的父类A;调用者依然是C,parent在这里,只是起到“转发调用者”的作用,是C要调用A中的Who static :: who(); //这里,因为调用者是C,等价于C::who() A::foo(); //将调用者改为A B::foo(); //将调用者改为B static::foo(); // 因为调用者是C,此时相当于C::foo(); parent::foo(); // parent指的是当前类的父类A;调用者依然是C,parent在这里,只是起到“转发调用者”的作用,是C要调用A中的foo,在A的foo中,static::who()相当于C::who() self::foo(); // self指的是当前类B;调用者依然是C,self在这里,只是起到“转发调用者”的作用,是C要调用B中的foo,B中的foo继承与A,在A的foo中,static::who()相当于C::who() } public static function who() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } } class C extends B { public static function who() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } } C::test();
执行结果如下:
C调用了B的who
C调用了A的who
C调用了C的who
A调用了A的who
B调用了B的who
C调用了C的who
C调用了C的who
C调用了C的who
其中,get_called_class 方法,是获取后期静态绑定("Late Static Binding")类的名称,即调用者的类名,在PHP5及以上版本,可以通过static::class获取调用者的类名。
self永远指向定义它的类。即你在哪里写了self,self就代表哪个类。
跟self类似,parent指向的是定义它的类的父类。
static指向了当前的调用域(calling scope),而不是定义它的地方代表的域。也就是说static绑定了调用方法的类,而不是定义方法的类。
手册上有这么一句话:后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者self:: 将转发调用信息
转发调用
class A { public static function who() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test();
输出结果:B调用了A的who
static调用私有的方法
实例1
class A { private function foo() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } public function test() { static::foo(); //此时调用者是B } } class B extends A { } $b = new B(); $b->test();
输出结果:B调用了A的foo
手册上面说A中的 foo() will be copied to B, hence its scope will still be A ,也就是说foo方法会复制到B中,但是A是的foo是私有的方法,怎么能复制到B呢?
我认为,static::foo首先会判断B中是否有foo方法,没有找到,然后就调用A中的私有foo。
实例2
class A { private function foo() { echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } public function test() { static::foo(); } } class B extends A { public function foo() { /* original method is replaced; the scope of the new one is C */ echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n"; } } $b = new B(); $b->test();
输出结果:C调用了C的foo
若将B中的foo方法改为私有,则会报错:PHP Fatal error: Call to private metho