这段时间看项目后台的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中设计模式的时候,你会感到很轻松的。

最新文章

  1. SSE: server-sent events
  2. import javax.servlet.FilterConfig;
  3. [转]使用 Minidumps 和 Visual Studio .NET 进行崩溃后调试
  4. 关于在Struts2框架下实现文件的上传功能
  5. iOS10相册相机闪退bug-b
  6. Composer PHP 依赖管理工具
  7. HDOJ2019数列有序!
  8. Microsoft Office Visio Professional 2007密钥
  9. UpdatePanel 无刷新弹出窗口
  10. Java Swing 使用总结(转载)
  11. List数据集动态排序
  12. 工作中使用seajs后的一些总结
  13. table 谷歌下不出现滚动条
  14. css雪碧图(css splite)
  15. JNI 对象处理 (转)
  16. python三种回收机制
  17. 如何下载最新Xshell版本、免费官方正版软件的技巧过程
  18. 基于阿里云 DNS API 实现的 DDNS 工具
  19. angular vue react web前端三大主流框架的对比
  20. Java面向对象(二)

热门文章

  1. linux下配置环境变量方式
  2. 用Jq遍历一个div里面的所有input 并判断是否为空?
  3. javascript函数中with的介绍
  4. 前端动画小记---bilibili ( ゜-゜)つロ客户下载小动画
  5. 【javascript】javascript设计模式mixin模式
  6. 插入外置网卡端口顺序混乱--linux系统
  7. 理解ASP.NET 5运行时命令:DNVM, DNX, 和DNU
  8. spring boot(5)-properties参数配置
  9. security权限控制
  10. C# 等值锁定