什么叫前期动态绑定呢?其实咱们在之前的文章 PHP 中的 static 中曾经说过这个货色了。明天咱们还是再次深刻的了解一下这个概念。
首先,咱们通过一段代码来引入前期动态绑定这一概念:
class A {public static function who() {echo __CLASS__, PHP_EOL;}
public static function test() {self::who();
}
}
class B extends A {public static function who() {echo __CLASS__, PHP_EOL;}
}
B::test(); // A
在这段代码中,咱们应用了 self 关键字,当应用 B 类调用 test() 静态方法时,self 指向的是 A 类的 who() 办法,因而,输入的是 A。别冲动,这是一般的动态绑定。self 关键字调用的内容取决于它定义时所在的类。也就是说不管怎么继承,用哪个子类来调用 test() 办法,self 关键字都会调用的是 A 类的 who() 办法。
而前期动态绑定呢?其实就有点像实例化的类对象,每个实例化的对象,调用的都是本身,而不是父类的属性办法。一般的动态调用可不是这样,然而事实中咱们又有这样的需要,就像实例化对象的调用形式一样来调用动态属性办法,这时,咱们就能够应用 static 关键字来实现前期动态绑定。
class C {public static function who() {echo __CLASS__, PHP_EOL;}
public static function test() {static::who();
}
}
class D extends C {public static function who() {echo __CLASS__, PHP_EOL;}
}
D::test(); // D
当应用 static 关键字后,这里 D 类调用的 test() 办法外部调用的 who() 就是 D 类本人了。
官网文档中的定义如下:
当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧局部);当进行非静态方法调用时,即为该对象所属的类。
该性能从语言外部角度思考被命名为“前期动态绑定”。“前期绑定”的意思是说,static:: 不再被解析为定义以后办法所在的类,而是在理论运行时计算的。也能够称之为“动态绑定”,因为它能够用于(但不限于)静态方法的调用。
除了 self 和 static 关键字外,咱们还有一个 parent 关键字,这个关键字的意义就很显著了,调用父类的动态内容。咱们同时用三个关键字一起来进行测试:
class E {public static function who() {echo __CLASS__, PHP_EOL;}
public static function test() {self::who();
static::who();}
}
class F extends E {public static function who() {echo __CLASS__, PHP_EOL;}
}
class G extends F {public static function who() {parent::who();
echo __CLASS__, PHP_EOL;
}
}
G::test();
// E
// F
// G
最初,咱们再来看两个 PHP 的办法,一个是 get_called_class() 办法,用来获取以后调用的是哪个类。在静态方法中能够依据调用形式判断以后类是哪个类来进行其余的业务逻辑操作。另一个是 forward_static_call() 办法,用于静态方法的调用。
class H {public static function who() {echo __CLASS__ . ':' . join(',', func_get_args()), PHP_EOL;
}
public static function test() {echo get_called_class(), PHP_EOL;
forward_static_call('who', 'a', 'b'); // xxx:a,b
forward_static_call(['I', 'who'], 'c', 'd'); // I:c,d
forward_static_call_array(['H', 'who'], ['e', 'f']); // H:e,f
}
}
class I extends H {public static function who() {echo __CLASS__ . ':' . join(',', func_get_args()), PHP_EOL;
}
}
function who() {echo 'xxx:' . join(',', func_get_args()), PHP_EOL;
}
H::test(); // H
// xxx:a,b
// I:c,d
// H:e,f
I::test(); // I
// xxx:a,b
// I:c,d
// H:e,f
留神,如果 forward_static_call() 不指定类名的话,将调用全局的办法。forward_static_call_array() 则是将参数应用数组进行传递。