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 相关文章推荐
一个域名查询的程序
Oct 09 PHP
php 数组的合并、拆分、区别取值函数集
Feb 15 PHP
PHP连接SQLServer2005 的问题解决方法
Jul 19 PHP
ThinkPHP中url隐藏入口文件后接收alipay传值的方法
Dec 09 PHP
php第一次无法获取cookie问题处理
Dec 15 PHP
php利用scws实现mysql全文搜索功能的方法
Dec 25 PHP
PHP统计当前在线用户数实例讲解
Oct 21 PHP
thinkPHP简单遍历数组方法分析
May 16 PHP
Laravel框架路由管理简单示例
May 07 PHP
PHP消息队列实现及应用详解【队列处理订单系统和配送系统】
May 20 PHP
php字符串截取函数mb_substr用法实例分析
Jun 25 PHP
详解php反序列化
Jun 10 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变量作用域的深入解析
2013/06/03 PHP
基于flush()不能按顺序输出时的解决办法
2013/06/29 PHP
WordPress中用于更新伪静态规则的PHP代码实例讲解
2015/12/18 PHP
详解使用php-cs-fixer格式化代码
2020/09/16 PHP
csdn 批量接受好友邀请
2009/02/19 Javascript
让 JavaScript 轻松支持函数重载 (Part 2 - 实现)
2009/08/04 Javascript
javascript验证只能输入数字和一个小数点示例
2013/10/21 Javascript
cookie中的path与domain属性详解
2013/12/18 Javascript
jquery ajax跨域解决方法(json方式)
2014/02/04 Javascript
js获取域名的方法
2015/01/27 Javascript
JavaScript判断字符长度、数字、Email、电话等常用判断函数分享
2015/04/01 Javascript
被遗忘的javascript的slice() 方法
2015/04/20 Javascript
jQuery拖拽插件gridster使用指南
2015/04/21 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
AngularJS HTML DOM详解及示例代码
2016/08/17 Javascript
javascript实现的左右无缝滚动效果
2016/09/19 Javascript
基于JS实现横线提示输入验证码随验证码输入消失(js验证码的实现)
2016/10/27 Javascript
BootStrap3中模态对话框的使用
2017/01/06 Javascript
React + webpack 环境配置的方法步骤
2017/09/07 Javascript
除Console.log()外更多的Javascript调试命令
2018/01/24 Javascript
nodejs多版本管理总结
2018/04/03 NodeJs
jQuery实现合并表格单元格中相同行操作示例
2019/01/28 jQuery
JavaScript检测是否开启了控制台(F12调试工具)
2020/10/02 Javascript
python处理图片之PIL模块简单使用方法
2015/05/11 Python
Python 爬虫之Beautiful Soup模块使用指南
2018/07/05 Python
python实现文本界面网络聊天室
2018/12/12 Python
python判断一个数是否能被另一个整数整除的实例
2018/12/12 Python
Python minidom模块用法示例【DOM写入和解析XML】
2019/03/25 Python
python3 简单实现组合设计模式
2020/07/02 Python
利用CSS3的线性渐变linear-gradient制作边框的示例
2016/06/02 HTML / CSS
ddl,dml和dcl的含义
2016/05/08 面试题
九年级科学教学反思
2014/01/29 职场文书
暑期社会实践感言
2014/02/25 职场文书
《雷雨》教学反思
2016/02/20 职场文书
2016年党员创先争优承诺书
2016/03/25 职场文书
2019暑假学生安全口号
2019/06/27 职场文书