“延迟静态绑定”是 PHP5.3 之后的引进的概念,用来解决 PHP 面向对象中 self
关键词的“静态绑定”需要被“延迟”的问题。
首先来看一个大部分资料中经常引用的例子:
class A
{
public static function echoClass()
{
echo __CLASS__;
}
public static function test()
{
self::echoClass();
}
}
class B extends A
{
public static function echoClass()
{
echo __CLASS__;
}
}
B::test(); //输出A
按照大多数初学者的常规思维,既然类A中的 test
方法本质上是调用的自身的 echoClass
这个方法,echoClass
这个方法的作用是打印“自身”的类名称,类B既然继承自类A,自然也默认会继承类A中的 test
方法,那么调用类B中的 test
方法也应该打印类B自身的类名,但为什么最终的结果却反而是打印了类B的名称呢?
实际上,在 php 底层解析过程中,self
关键词是一个相对特殊的的地方,self 指向的是“定义” self
所在方法的类,而不是实际“调用” self
所在方法的类。听上去是比较枯燥,怎么理解这段话呢?就是说,php 语法解释器在解释执行 php 代码的时候,例子中类A的 self
关键词被解释器优先“绑定”到包含 self
所在方法的类A,后面无论什么时候调用 test
这个方法(即使是在继承类B中),self
关键词都是指代的是类A,所以 B::test()
其实等同于 A::test()
,代码输出的结果当然是 A 而不是 B 了。
在 php5.3 之前的版本中,self
关键词的静态绑定被添加了严格的限制,这样设计的目的现在已经无法得知,但为了让代码逻辑更加贴近现实,开发者们提出过许多笨拙的解决办法,直到5.3版本之后的 php 语法中,新关键字 static
的引入较好地解决了“延迟静态绑定”的问题,这里的 static
当然不再是简单地用来申明静态方法和属性的关键词,延迟静态绑定这一概念中的 static
被赋予了类似 self
关键词的含义,关键的是 static
指代的是在实际执行时候被调用的类,而不是包含 static
关键词的所在类,前面的例子可以改写为:
class A
{
public static function echoClass()
{
echo __CLASS__;
}
public static function test()
{
static::echoClass(); // 利用static关键词延迟静态绑定
}
}
class B extends A
{
public static function echoClass()
{
echo __CLASS__;
}
}
B::test(); //输出B