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 相关文章推荐
ADODB的数据库封包程序库
Dec 31 PHP
支持php4、php5的mysql数据库操作类
Jan 10 PHP
Php注入点构造代码
Jun 14 PHP
用PHP实现Ftp用户的在线管理
Feb 16 PHP
Laravel 5框架学习之子视图和表单复用
Apr 09 PHP
基于linnux+phantomjs实现生成图片格式的网页快照
Apr 15 PHP
php递归遍历多维数组的方法
Apr 18 PHP
php实现通过cookie换肤的方法
Jul 13 PHP
php中Ioc(控制反转)和Di(依赖注入)
May 07 PHP
php 人员权限管理(RBAC)实例(推荐)
May 24 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
Nov 14 PHP
PHP结合Ffmpeg快速搭建流媒体服务的实践记录
Oct 31 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在线生成ico文件的代码
2007/10/09 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
discuz加密解密函数使用方法和中文注释
2014/01/21 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
js停止输出代码
2008/07/20 Javascript
JS分页效果示例
2013/10/11 Javascript
WEB前端设计师常用工具集锦
2014/12/09 Javascript
JavaScript中setUTCFullYear()方法的使用简介
2015/06/12 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
JavaScript使用delete删除数组元素用法示例【数组长度不变】
2017/01/17 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
2017/04/25 jQuery
jQuery实现的淡入淡出与滑入滑出效果示例
2018/04/18 jQuery
security.js实现的RSA加密功能示例
2018/06/06 Javascript
Angular 利用路由跳转到指定页面的指定位置方法
2018/08/31 Javascript
使用vue开发移动端管理后台的注意事项
2019/03/07 Javascript
关于layui 下拉列表的change事件详解
2019/09/20 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
2019/12/20 Javascript
[51:34]Ti4主赛事胜者组 DK vs EG 2
2014/07/19 DOTA
python命令行参数sys.argv使用示例
2014/01/28 Python
基于Python实现一个简单的银行转账操作
2016/03/06 Python
Python实现字典按照value进行排序的方法分析
2017/12/23 Python
Python 爬取携程所有机票的实例代码
2018/06/11 Python
python 找出list中最大或者最小几个数的索引方法
2018/10/30 Python
Python数据类型之List列表实例详解
2019/05/08 Python
Python datetime包函数简单介绍
2019/08/28 Python
Jupyter notebook快速入门教程(推荐)
2020/05/18 Python
Bose英国官方网站:美国知名音响品牌
2020/01/26 全球购物
中国电子产品批发商/跨境电商/外贸网:Sunsky-online
2020/04/20 全球购物
记账会计岗位职责
2014/06/16 职场文书
机关党员三严三实心得体会
2014/10/13 职场文书
2015年卫生监督工作总结
2015/05/21 职场文书
环保宣传语大全
2015/07/13 职场文书
2015国庆节宣传语
2015/07/14 职场文书
《分一些蚊子进来》读后感3篇
2020/01/09 职场文书
聊聊SpringBoot自动装配的魔力
2021/11/17 Java/Android
德劲DE1107指针试高灵敏度全波段收音机机评
2022/04/05 无线电