PHP延迟静态绑定的深入讲解

作者:JellyThink 时间:2024-06-05 15:42:51 

前言

所谓延迟静态绑定,顾名思义,静态调用时::符号左侧的部分的的绑定是延迟,也就是说不再被解析为定义当前方法所在的类,而是在实际运行时计算的。本文主要介绍了关于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中设计模式的时候,你会感到很轻松的。

总结

就是一个很简单的知识点,但是却非常有用,总结起来,还是查了一些资料,补充一下知识点。温故而知新。好了,希望对大家有帮助。如果大家有什么建议,让我的文章写的更好,尽管提出来,我需要大家的帮助。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对asp之家的支持。

来源:https://www.jellythink.com/archives/237

标签:php,延迟,静态绑定
0
投稿

猜你喜欢

  • python下10个简单实例代码

    2023-01-31 19:38:20
  • 微信小程序实现给嵌套template模板传递数据的方式总结

    2024-05-22 10:31:50
  • Go语言读写锁RWMutex的源码分析

    2024-05-09 09:47:55
  • Python np.where()的详解以及代码应用

    2023-02-15 18:33:01
  • python 中 .py文件 转 .pyd文件的操作

    2022-02-17 09:59:38
  • Python 转换文本编码实现解析

    2022-07-15 15:58:49
  • php中如何判断一个网页请求是ajax请求还是普通请求

    2023-10-13 14:42:30
  • sqlserver数据库移动数据库路径的脚本示例

    2024-01-28 05:06:49
  • ORACLE8的分区管理

    2010-07-30 13:18:00
  • Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解

    2024-05-03 15:29:17
  • Python中的十大图像处理工具(小结)

    2021-02-04 09:17:51
  • Django自定义模板过滤器和标签的实现方法

    2023-08-12 12:24:51
  • 文字链接,怎么办?

    2008-08-04 13:18:00
  • TensorFlow查看输入节点和输出节点名称方式

    2022-11-27 04:50:11
  • Python 操作 MySQL数据库

    2024-01-17 17:46:17
  • 读写xml文件的2个小函数

    2007-08-23 12:59:00
  • vue之prop与$emit的用法说明

    2024-05-09 15:20:41
  • Mysql元数据如何生成Hive建表语句注释脚本详解

    2024-01-18 12:52:05
  • Java连接mysql数据库代码实例程序

    2024-01-22 03:01:26
  • 基于原生JavaScript实现SPA单页应用

    2024-04-30 09:59:43
  • asp之家 网络编程 m.aspxhome.com