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 相关文章推荐
smarty静态实验表明,网络上是错的~呵呵
Nov 25 PHP
MYSQL环境变量设置方法
Jan 15 PHP
php中获取关键词及所属来源搜索引擎名称的代码
Feb 15 PHP
用PHP实现的四则运算表达式计算实现代码
Aug 02 PHP
PHP隐形一句话后门,和ThinkPHP框架加密码程序(base64_decode)
Nov 02 PHP
PHP字符串函数系列之nl2br(),在字符串中的每个新行 (\n) 之前插入 HTML 换行符br
Nov 10 PHP
探讨多键值cookie(php中cookie存取数组)的详解
Jun 06 PHP
php上传图片之时间戳命名(保存路径)
Aug 15 PHP
php使用ZipArchive提示Fatal error: Class ZipArchive not found in的解决方法
Nov 04 PHP
php禁用函数设置及查看方法详解
Jul 25 PHP
php安装php_rar扩展实现rar文件读取和解压的方法
Nov 17 PHP
thinkPHP5.0框架配置格式、加载解析与读取方法
Mar 17 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
聊天室php&amp;mysql(一)
2006/10/09 PHP
PHP日期和时间函数的使用示例详解
2020/08/06 PHP
二级域名转向类
2006/11/09 Javascript
网站页面自动跳转实现方法PHP、JSP(下)
2010/08/01 Javascript
jQuery学习笔记之jQuery的DOM操作
2010/12/22 Javascript
JavaScript传递变量: 值传递?引用传递?
2011/02/22 Javascript
jQuery中setTimeout的几种使用方法小结
2013/04/07 Javascript
Javascript常用字符串判断函数代码分享
2014/12/08 Javascript
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
JavaScript如何实现在文本框(密码框)输入提示语
2015/12/25 Javascript
AngularJS中如何使用$http对MongoLab数据表进行增删改查
2016/01/23 Javascript
jQuery搜索框效果实现代码(百度关键词联想)
2021/02/25 Javascript
JavaScript中捕获与冒泡详解及实例
2017/02/03 Javascript
Express与NodeJs创建服务器的两种方法
2017/02/06 NodeJs
利用n 升级工具升级Node.js版本及在mac环境下的坑
2017/02/15 Javascript
Javascript实现信息滚动效果
2017/05/18 Javascript
js自定义Tab选项卡效果
2017/06/05 Javascript
Angularjs实现控制器之间通信方式实例总结
2018/03/27 Javascript
webpack打包react项目的实现方法
2018/06/21 Javascript
JavaScript寄生组合式继承原理与用法分析
2019/01/11 Javascript
koa2 用户注册、登录校验与加盐加密的实现方法
2019/07/22 Javascript
vue相同路由跳转强制刷新该路由组件操作
2020/08/05 Javascript
[03:49]2016完美“圣”典风云人物:AMS专访
2016/12/06 DOTA
python实现按行切分文本文件的方法
2016/04/18 Python
解决Python中字符串和数字拼接报错的方法
2016/10/23 Python
python检查URL是否正常访问的小技巧
2017/02/25 Python
解决Tensorflow安装成功,但在导入时报错的问题
2018/06/13 Python
python bluetooth蓝牙信息获取蓝牙设备类型的方法
2019/11/29 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
2020/11/26 Python
css3 flex布局 justify-content:space-between 最后一行左对齐
2020/01/02 HTML / CSS
施工安全生产承诺书
2014/05/23 职场文书
归元寺导游词
2015/02/06 职场文书
中学生打架《检讨书》范文
2019/08/12 职场文书
Python 语言实现六大查找算法
2021/06/30 Python
Python+OpenCV实现图片中的圆形检测
2022/04/07 Python