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程序员最常犯的11个MySQL错误小结
Nov 20 PHP
PHP网站备份程序代码分享
Jun 10 PHP
七款最流行的PHP本地服务器分享
Feb 19 PHP
Window下PHP三种运行方式图文详解
Jun 11 PHP
php设计模式之命令模式使用示例
Mar 02 PHP
php通过ksort()函数给关联数组按照键排序的方法
Mar 18 PHP
PHP在线书签系统分享
Jan 04 PHP
php图片上传类 附调用方法
May 15 PHP
PHP使用GD库输出汉字的方法【测试可用】
Nov 10 PHP
基于Codeigniter框架实现的student信息系统站点动态发布功能详解
Mar 23 PHP
Thinkphp5.0自动生成模块及目录的方法详解
Apr 17 PHP
PHP控制循环操作的时间
Apr 01 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模板技术[转]
2007/01/04 PHP
thinkphp中连接oracle时封装方法无法用的解决办法
2013/06/17 PHP
PHP下载远程文件到本地存储的方法
2015/03/24 PHP
十个PHP高级应用技巧果断收藏
2015/09/25 PHP
PHP获取昨天、今天及明天日期的方法
2016/02/03 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例
2017/09/15 PHP
javascript arguments 传递给函数的隐含参数
2009/08/21 Javascript
jQuery阻止冒泡和HTML默认操作
2010/11/17 Javascript
基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
2013/04/26 Javascript
javascript检测两个数组是否相似
2015/05/19 Javascript
jQuery实现html表格动态添加新行的方法
2015/05/28 Javascript
JS实现自动切换文字的导航效果代码
2015/08/27 Javascript
vue.js实现含搜索的多种复选框(附源码)
2017/03/23 Javascript
解决vue 格式化银行卡(信用卡)每4位一个符号隔断的问题
2018/09/14 Javascript
js常见遍历操作小结
2019/06/06 Javascript
浅谈element中InfiniteScroll按需引入的一点注意事项
2020/06/05 Javascript
解决vue-router 嵌套路由没反应的问题
2020/09/22 Javascript
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
python通过伪装头部数据抵抗反爬虫的实例
2018/05/07 Python
python实现俄罗斯方块
2018/06/26 Python
Python面向对象之静态属性、类方法与静态方法分析
2018/08/24 Python
python使用__slots__让你的代码更加节省内存
2018/09/05 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
python实现一行输入多个值和一行输出多个值的例子
2019/07/16 Python
python科学计算之scipy——optimize用法
2019/11/25 Python
Numpy中np.random.rand()和np.random.randn() 用法和区别详解
2020/10/23 Python
Python常用外部指令执行代码实例
2020/11/05 Python
用HTML5 Canvas API中的clearRect()方法实现橡皮擦功能
2016/03/15 HTML / CSS
HTML5 中新的全局属性(整理)
2013/07/31 HTML / CSS
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
小学生暑假安全公约
2015/07/14 职场文书
离婚民事起诉状
2015/08/03 职场文书
初中军训感想
2015/08/07 职场文书
2016个人先进事迹材料范文
2016/03/01 职场文书
java中用float时,数字后面加f,这样是为什么你知道吗
2021/09/04 Java/Android