从PHP 5.3.0开始,PHP增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
该功能从语言内部角度考虑被命名为”后期静态绑定“。”后期绑定“的意思是说,static::不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为”静态绑定“,因为它可以用于(但不限于)静态方法的调用。
使用self:: 或者 __CLASS__对当前类的静态引用,取决于定义当前方法所在的类:
Example #1 self:: 用法
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
以上例程会输出:
A
后期静态绑定试图通过引入一个关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用test()时引用的类是B而不是A。最终决定不引入新的关键字,而是使用已经预留的static关键字。
Example #2 static:: 简单用法
<?php
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
Note:
static:: 在处理静态方法时与 $this 是不同的。 $this-> 会遵循继承规则,但是 static:: 不会。该差异将稍后在本手册中详细说明。
Example #3 static:: 用于非静态引用
<?php
class TestChild extends TestParent {
public function __construct() {
static::who();
}
public function test() {
$o = new TestParent();
}
public static function who() {
echo __CLASS__."
";
}
}
class TestParent {
public function __construct() {
static::who();
}
public static function who() {
echo __CLASS__."
";
}
}
$o = new TestChild;
$o->test();
?>
以上例程会输出:
TestChild TestParent
Note:
后期静态绑定的处理方式解决了以往完全没有办法解决的静态调用。另外一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。
Example #4 转发和非转发调用
<?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();
}
public static function who() {
echo __CLASS__." ";
}
}
class C extends B {
public static function who() {
echo __CLASS__." ";
}
}
C::test();
?>以上例程会输出:
A C C
在PHP中有很多方式来触发一个方法的调用,例如回调函数或者魔术方法。因为后期静态绑定取决于运行时的信息,因此在特殊情况下可能会得到意想不到的结果。
Example #5 在魔术方法中使用后期静态绑定
<?php
class A {
protected static function who() {
echo __CLASS__."
";
}
public function __get($var) {
return static::who();
}
}
class B extends A {
protected static function who() {
echo __CLASS__."
";
}
}
$b = new B;
$b->foo;
?>
以上例程会输出:
B