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 相关文章推荐
php设计模式 Command(命令模式)
Jun 26 PHP
php语言流程控制中的主动与被动
Nov 05 PHP
深入理解curl类,可用于模拟get,post和curl下载
Jun 08 PHP
ThinkPHP使用UTFWry地址库进行IP定位实例
Apr 01 PHP
关于php支持分块与断点续传文件下载功能代码
May 09 PHP
PHP安全的URL字符串base64编码和解码
Jun 19 PHP
php调用KyotoTycoon简单实例
Apr 02 PHP
php阿拉伯数字转中文人民币大写
Dec 21 PHP
Laravel中Facade的加载过程与原理详解
Sep 22 PHP
PHP仿tp实现mvc框架基本设计思路与实现方法分析
May 23 PHP
微信推送功能实现方式图文详解
Jul 12 PHP
PHPUnit + Laravel单元测试常用技能
Nov 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
php检测用户是否用手机(Mobile)访问网站的类
2014/01/09 PHP
Thinkphp实现MySQL读写分离操作示例
2014/06/25 PHP
Zend Framework自定义Helper类相关注意事项总结
2016/03/14 PHP
PHP中in_array函数使用的问题与解决办法
2016/09/11 PHP
微信公众平台开发-微信服务器IP接口实例(含源码)
2017/03/05 PHP
js checkbox(复选框) 使用集锦
2009/04/28 Javascript
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
2010/08/07 Javascript
js的一些常用方法小结
2011/06/29 Javascript
js自动下载文件到本地的实现代码
2013/04/28 Javascript
Javascript连接多个数组不用concat来解决
2014/03/24 Javascript
JavaScript使用Replace进行字符串替换的方法
2015/04/14 Javascript
AngularJS的ng Http Request与response格式转换方法
2016/11/07 Javascript
将angular.js项目整合到.net mvc中的方法详解
2017/06/29 Javascript
ES6正则表达式扩展笔记
2017/07/25 Javascript
three.js中文文档学习之通过模块导入
2017/11/20 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
七行JSON代码把你的网站变成移动应用过程详解
2019/07/09 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
python自动化测试实例解析
2014/09/28 Python
Python去除列表中重复元素的方法
2015/03/20 Python
Java中重定向输出流实现用文件记录程序日志
2015/06/12 Python
Python中常见的数据类型小结
2015/08/29 Python
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
pytorch-神经网络拟合曲线实例
2020/01/15 Python
python和php学习哪个更有发展
2020/06/17 Python
浅析HTML5中的download属性使用
2019/03/13 HTML / CSS
美国领先的眼镜和太阳镜在线零售商:Glasses.com
2019/08/26 全球购物
Java多态性的定义以及类型
2014/09/16 面试题
师范教师大学生职业生涯规划范文
2014/01/05 职场文书
复核员上岗演讲稿
2014/01/05 职场文书
问卷调查计划书
2014/01/10 职场文书
商场促销活动方案
2014/02/08 职场文书
2014年学校德育工作总结
2014/12/05 职场文书
MySQL 亿级数据导入导出及迁移笔记
2021/06/18 MySQL
postgresql之greenplum字符串去重拼接方式
2023/05/08 PostgreSQL