前言
所谓延迟静态绑定,顾名思义,静态调用时::符号左侧的部分的的绑定是延迟,也就是说不再被解析为定义当前方法所在的类,而是在实际运行时计算的。本文主要介绍了关于PHP延迟静态绑定的相关内容,下面话不多说了,来一起看看详细的介绍吧。
嗅到了坏的味道
这段时间看项目后台的PHP代码,看到了类似于以下的一段代码,我把它抽出来:
<?php class DBHandler { function get() {} } class MySQLHandler extends DBHandler { // 这里一个create public static function create() { echo "MySQL"; return new self(); } public function get() { echo "MySQL get()"; } } class MemcachedHandler extends DBHandler { // 这里又有一个create public static function create() { echo "Memcached"; return new self(); } public function get() { echo "Memcached get"; } } function get(DBHandler $handler) { $handler->get(); } $dbHandler = MySQLHandler::create(); get($dbHandler); ?>
有没有嗅到坏代码的味道?可以看到,在MySQLHandler和MemcachedHandler类中,都有一个create函数,除掉我的输出语句,发现它们一模一样,这就是代码冗余。是的,需要进行代码重构。
进行简单的重构
代码重构无处不在,只要你想,你觉的有改进,就需要敲起键盘开始干活。来吧,对上面的代码进行重构,如下:
<?php class DBHandler { public static function create() { echo "create"; return new self(); } function get() {} } class MySQLHandler extends DBHandler { public function get() { echo "MySQL get()"; } } class MemcachedHandler extends DBHandler { public function get() { echo "Memcached get"; } } function get(DBHandler $handler) { $handler->get(); } $dbHandler = MySQLHandler::create(); get($dbHandler); ?>
将create函数移到DBHandler类中,看起来还不错,至少少了一坨那糟糕的代码。
貌似是错的
运行一下,却发现,并没有打印出我们期望的 MySQL get() 。什么情况?这说明,并没有调用MySQLHandler的get函数,但是代码明明调用了啊,这说明, new self() 这句代码有问题。这有什么问题?这就需要说到今天总结的重点了————延迟静态绑定。
延迟静态绑定
在PHP5.3以后引入了延迟静态绑定。再看下面这段代码:
<?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,但是我希望它输出B,这就是问题的所在。这也是 self 和 __CLASS__ 的限制。使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类。所以,这就很好的解释了为什么上面的代码输出了A。但是,如果我们需要输出B呢?可以这么干:
<?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(); ?>
后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。
这就是后期静态绑定的根本————static关键字的另类用法。对于文章一开始的例子,可以这么改:
return new static(); // 改变这里,后期静态绑定
这种使用后期静态绑定,在使用PHP实现23中设计模式的时候,你会感到很轻松的。
总结
就是一个很简单的知识点,但是却非常有用,总结起来,还是查了一些资料,补充一下知识点。温故而知新。好了,希望对大家有帮助。如果大家有什么建议,让我的文章写的更好,尽管提出来,我需要大家的帮助。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍PHP延迟静态绑定示例分享,包括了PHP延迟静态绑定示例分享的使用技巧和注意事项,需要的朋友参考一下 没怎么用过这个新特性,其实也不算新啦,试试吧,现在静态类的继承很方便了
本文向大家介绍php延迟静态绑定实例分析,包括了php延迟静态绑定实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php延迟静态绑定的方法。分享给大家供大家参考。具体分析如下: php延迟静态绑定:指类的self,不是以定义时为准,而是以计算时的运行结果为准。先看一个实例 说明: (1)子类实例化对象 $stu 调用say方法时,是在父类Human内运行的,所以,say()里的
本文向大家介绍PHP Static延迟静态绑定用法分析,包括了PHP Static延迟静态绑定用法分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP Static延迟静态绑定用法。分享给大家供大家参考,具体如下: PHP5.3以后引入了延迟静态绑定static,它是为了解决什么问题呢?php的继承模型中有一个存在已久的问题,那就是在父类中引用扩展类的最终状态比较困难。来看一个例子。
在java-9中,在CompletableFuture类中引入了新方法completeOnTimeout 我不明白的是为什么它在其实现中使用静态: 在哪里 对我来说,这是一种非常奇怪的方法,因为它可能会成为整个应用程序的瓶颈:唯一的,只有一个线程保留在所有可能的任务的池内? 我错过了什么? P、 它看起来像: > 此代码的作者不愿意提取此逻辑,而是更愿意重用ScheduledThreadPoolE
问题内容: 我对动态绑定和静态绑定感到非常困惑。我已经读过,在编译时确定对象的类型称为静态绑定,而在运行时确定它的称为动态绑定。 下面的代码会发生什么: 静态绑定还是动态绑定? 这表明什么样的多态性? 问题答案: 您的示例是 动态绑定 ,因为在运行时确定类型是什么,并调用适当的方法。 现在假设您也具有以下两种方法: 即使您更改为 这将打印出来,因为对的调用使用 静态绑定 ,并且编译器仅知道其类型。
静态绑定还是动态绑定? 这显示了什么样的多态性?