PHP延迟静态绑定的深入讲解


Posted in PHP onApril 02, 2018

前言

所谓延迟静态绑定,顾名思义,静态调用时::符号左侧的部分的的绑定是延迟,也就是说不再被解析为定义当前方法所在的类,而是在实际运行时计算的。本文主要介绍了关于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 相关文章推荐
用Flash图形化数据(一)
Oct 09 PHP
推荐个功能齐全的发送PHP邮件类
Jan 03 PHP
DEDE采集大师官方留后门的删除办法
Jan 08 PHP
php若干单维数组遍历方法的比较
Sep 20 PHP
PHP简洁函数(PHP简单明了函数语法)
Jun 10 PHP
php生成静态文件的多种方法分享
Jul 17 PHP
10个超级有用值得收藏的PHP代码片段
Jan 22 PHP
PHP简单实现文本计数器的方法
Apr 28 PHP
掌握PHP垃圾回收机制详解
Mar 13 PHP
Yii框架自定义数据库操作组件示例
Nov 11 PHP
laravel5.6 框架邮件队列database驱动简单demo示例
Jan 26 PHP
Laravel框架中队列和工作(Queues、Jobs)操作实例详解
Apr 06 PHP
PHP设计模式之装饰器模式定义与用法详解
Apr 02 #PHP
PHP设计模式之状态模式定义与用法详解
Apr 02 #PHP
PHP设计模式之模板方法模式定义与用法详解
Apr 02 #PHP
PHP实现动态获取函数参数的方法示例
Apr 02 #PHP
PHP调用其他文件中的类
Apr 02 #PHP
为何说PHP引用是个坑,要慎用
Apr 02 #PHP
PHP实现的一致性Hash算法详解【分布式算法】
Mar 31 #PHP
You might like
浅谈Windows下 PHP4.0与oracle 8的连接设置
2006/10/09 PHP
PHP中的正规表达式(二)
2006/10/09 PHP
php代码把全角数字转为半角数字
2007/12/10 PHP
Mysql的GROUP_CONCAT()函数使用方法
2008/03/28 PHP
PHP实现MySQL更新记录的代码
2008/06/07 PHP
Ping服务的php实现方法,让网站快速被收录
2012/02/04 PHP
ThinkPHP采用GET方式获取中文参数查询无结果的解决方法
2014/06/26 PHP
取得单条网站评论以数组形式进行输出
2014/07/28 PHP
PHP使用imagick扩展实现合并图像的方法
2017/04/25 PHP
Laravel Validator 实现两个或多个字段联合索引唯一
2019/05/08 PHP
在Z-Blog中运行代码[html][/html](纯JS版)
2007/03/25 Javascript
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
js采用map取到id集合组并且实现点击一行选中一行
2013/12/16 Javascript
window.location不跳转的问题解决方法
2014/04/17 Javascript
js实现div闪烁原理及实现代码
2014/06/24 Javascript
通过点击jqgrid表格弹出需要的表格数据
2015/12/02 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
2016/05/25 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
react-router browserHistory刷新页面404问题解决方法
2017/12/29 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
2019/08/20 Javascript
vue实现购物车案例
2020/05/30 Javascript
Python IDE PyCharm的基本快捷键和配置简介
2015/11/04 Python
在centos7中分布式部署pyspider
2017/05/03 Python
Python中执行存储过程及获取存储过程返回值的方法
2017/10/07 Python
Python搭建代理IP池实现检测IP的方法
2019/10/27 Python
浅析matlab中imadjust函数
2020/02/27 Python
Python 找出出现次数超过数组长度一半的元素实例
2020/05/11 Python
Python新手学习标准库模块命名
2020/05/29 Python
python装饰器三种装饰模式的简单分析
2020/09/04 Python
New Balance英国官方网站:始于1906年,百年慢跑品牌
2016/12/07 全球购物
工业设计毕业生自荐信
2014/04/13 职场文书
学雷锋活动总结范文
2014/04/25 职场文书
解除租房协议书
2014/12/03 职场文书
2015年教研组工作总结
2015/05/04 职场文书
道歉情书大全
2015/05/12 职场文书
SpringBoot项目部署到阿里云服务器的实现步骤
2022/06/28 Java/Android