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网站来路获取代码(针对搜索引擎)
Jun 08 PHP
PHP中改变图片的尺寸大小的代码
Jul 17 PHP
PHP学习笔记 用户注册模块用户类以及验证码类
Sep 20 PHP
服务器变量 $_SERVER 的深入解析
Jul 02 PHP
PHP删除数组中特定元素的两种方法
Jul 02 PHP
微信公众平台开发实现2048游戏的方法
Apr 15 PHP
Yii 2.0中场景的使用教程
Jun 02 PHP
Laravel如何使用数据库事务及捕获事务失败后的异常详解
Oct 23 PHP
PHP实现的无限分类类库定义与用法示例【基于thinkPHP】
Aug 06 PHP
php的命名空间与自动加载实现方法
Aug 25 PHP
解决windows上php xdebug 无法调试的问题
Feb 19 PHP
PHP实现创建一个RPC服务操作示例
Feb 23 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图片水印添加、压缩、剪切的封装类实现
2020/04/18 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
2016/01/05 PHP
yii2缓存Caching基本用法示例
2016/07/18 PHP
Laravel中使用Queue的最基本操作教程
2017/12/27 PHP
js实现简单鼠标跟随效果的方法
2015/04/10 Javascript
jQuery实现的在线答题功能
2015/04/12 Javascript
js实现向右横向滑出的二级菜单效果
2015/08/27 Javascript
基于javaScript的this指向总结
2017/07/22 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
解决vue中对象属性改变视图不更新的问题
2018/02/23 Javascript
nodejs之koa2请求示例(GET,POST)
2018/08/07 NodeJs
详解node和ES6的模块导出与导入
2020/02/19 Javascript
微信小程序用户盒子、宫格列表的实现
2020/07/01 Javascript
解决vue项目打包上服务器显示404错误,本地没出错的问题
2020/11/03 Javascript
[00:31]DOTA2荣耀之路7:Miracle-空血无敌斩
2018/05/31 DOTA
[33:19]完美世界DOTA2联赛PWL S2 PXG vs InkIce 第一场 11.26
2020/11/30 DOTA
python paramiko实现ssh远程访问的方法
2013/12/03 Python
Python实现partial改变方法默认参数
2014/08/18 Python
Python装饰器用法实例总结
2018/05/26 Python
关于python列表增加元素的三种操作方法
2018/08/22 Python
Django 在iframe里跳转顶层url的例子
2019/08/21 Python
Python实现元素等待代码实例
2019/11/11 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
快速了解Python开发环境Spyder
2020/06/29 Python
使用Python解析Chrome浏览器书签的示例
2020/11/13 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
CSS3中的Transition过度与Animation动画属性使用要点
2016/05/20 HTML / CSS
你不知道的5个HTML5新功能
2016/06/28 HTML / CSS
html5 canvas移动浏览器上实现图片压缩上传
2016/03/11 HTML / CSS
如何为DataGridView添加一个定制的Column Type
2014/01/21 面试题
高中生自我评语大全
2014/01/19 职场文书
公司保洁员管理制度
2015/08/04 职场文书
简历自我评价:教师师德表现自我评价
2019/04/24 职场文书
Python进阶学习之带你探寻Python类的鼻祖-元类
2021/05/08 Python
Python 语言实现六大查找算法
2021/06/30 Python
shell进度条追踪指令执行时间的场景分析
2022/06/16 Servers