对于PHP 后期静态绑定的理解
在学静态方法调用的时候只学了 parent::
self::
调用静态方法,昨天突然看到一个兄弟的代码,写了一个 static::
,没见过啊~于是查了一下官方文档,发现了“后期静态绑定”这个功能,
下边这段
代码1:
class A {
public static function foo() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
运行结果是 A C C,估计有朋友跟我一样一开始也是不明所以。仔细研究了一下文档说的内容,结合自己的测试。基本上搞明白了这个功能的意思。
根据官方文档:
后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 ::运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static::以及forward_static_call()。可用get_called_class()函数来得到被调用的方法所在的类名,static::则指出了其范围。
这一段话的意思说白了就是:
类名::静态方法 这种方式是非转发调用 如: A::test()
self/parent/static :: 静态方法 这种方式就是 转发调用 如 static::test()
虽然 都是转发调用,其实只有static是后期静态绑定
代码2:
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
static::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
结果为 AB
原因是当调用静态绑定的方法时,由于转发调用,static::who()
绑定的是上一个“非转发调用”的类名,也就是B::test()
中的B,此时有人就问了,那代码1中的为什么是ACC不是AAC呢,在这里我也困惑了一阵子,其实文档中说的 上一个非转发调用类名说的不是很清楚(对我们这种菜鸟来说)。代码1中C::test()
调用到
A::foo();
parent::foo();
self::foo();
此时这三个方法都绑定到C类上了,而调用A::foo()
的时候 又是一个非转发调用,此时绑定者变为A,而之后的parent::foo()``self::foo()
是转发调用,仍然绑定在C上。