理解 PHP 延迟静态绑定 (late static bindings)
简单理解PHP延迟静态绑定
static::中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名。这个东西可以实现在父类中能够调用子类的方法和属性。
使用(static)关键字来表示这个别名,和静态方法,静态类没有半毛钱的关系,static::不仅支持静态类,还支持对象(动态类)。
预备概念
转发调用
所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。
非转发调用
那么非转发调用其实就是明确指定类名的静态调用(foo::bar())和非静态调用($foo->bar())
后期静态绑定原理
后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。
例子1,简单使用static::
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // 后期静态绑定从这里开始
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
以上例程会输出:
B
例子2,区分转发调用和非转发调用
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
例子3,使用场景举例
class Model
{
public static function find()
{
echo static::$name;
}
}
class Product extends Model
{
protected static $name = 'Product';
}
Product::find();
参考资料:
本帖已被设为精华帖!
本帖由 Summer
于 8年前 加精
高认可度评论:
例子1的结果应该是B吧,我在php7上跑了下也是B:smile:
例子1的结果应该是B吧,我在php7上跑了下也是B:smile:
1楼正解,的确是 B
如果是
self::who()
, 才是 A对啊 ,差点都怀疑自己
@jiyis 这个脸打得。。。。写完文章的没细看。。的确是B,已修正,谢谢
@CRQM :laughing: 没有没有,文章写的好了才会让人仔细看!
@jiyis 真是客气,社区氛围好!
:+1: 很详细,便于记忆+理解
学习了
例子2,parent::foo();为什么输出C?不甚明白,望高人指点迷津!
@garguntua 例子 2,parent::foo (); 为什么输出 C?
@Hanson 例子 2,parent::foo (); 为什么输出 C?
@learner
个人理解:
C::test();
中 ,这是调用明确指定类名的静态方法,属于“非转发调用”,这个“非转发调用”的类名C被存储下来。parent::foo();
属于转发调用,记录的最后一个”非转发调用“ 的类名不变,依然是C。static::who();
这个语句用到了static::
,也就是“后期静态绑定”。再看一下定义:而这个实时计算出来的类,按照工作原理,就是我们一直存储着的C。
test()
中的第二句,相当于在直接调用C::who();
。显然输出结果是C。