`
liuleiluwenhui
  • 浏览: 744 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
最近访客 更多访客>>
社区版块
存档分类
最新评论

PHP 5.4 全新 trait 语法

阅读更多

PHP 5.4 全新 trait 语法

文章转载于:http://blog.makingware.com/?p=97

<!-- .entry-meta -->
最近看 PHP 5.4 的 Changelog 时发现新增了 Trait 语法,根据 wiki 的说明,这个语法是为了解决代码的“水平复用”而诞生的。什么是“水平复用”呢?这里用一个相对简单的例子说明一下:

 

要理解水平复用,必须从 OOP 的 DRY 实践说起……
假设现在有三个业务类,它们都使用 ActiveRecord 模式实现持久化,那么代码看上去会像这样:

1 // 工具类
2 class ActiveRecord {}
3 // 业务类
4 class User extends ActiveRecord {}
5 class Article extends ActiveRecord {}
6 class Log extends ActiveRecord {}

然后,你发现 User 和 Article 的内容需要经常被读取,为了加快读取速度要用上 Cache,而 Log 大部分时候都是写入,很少读取,不需要使用 Cache。传统方法上,为了实现 Cache 读取,会把代码写成这样:

01 // 工具类
02 class ActiveRecord {}
03 // 业务类
04 class User extends ActiveRecord {
05     // 重载查询方法
06     function find() {
07         // 判断 Cache 在不在,读 Cache 然后返回
08     }
09 }
10 class Article extends ActiveRecord {
11     // 重载查询方法
12     function find() {
13         // 判断 Cache 在不在,读 Cache 然后返回
14     }
15 }
16 class Log extends ActiveRecord {}

这样明显有个问题,User 和 Article 使用 Cache 的代码是重复的!这时你可能想到把可以被 Cache 的类继承到另外一个叫 CachedActiveRecord 里面,把代码写成这样:

1 // 工具类
2 class ActiveRecord {}
3 class CachedActiveRecord extends ActiveRecord {}
4 // 业务类
5 class User extends CachedActiveRecord {}
6 class Article extends CachedActiveRecord {}
7 class Log extends ActiveRecord {}

这样的确解决了重复 Cache 代码的问题,但另外一个问题又来了:如果我要在 User 和 Article 实现不同的 Cache 策略呢?
这种方式只能实现固定的 Cache 策略,虽然可以通过 if..else../switch 来实现,但这样显然不符合 OOP 的原则。
于是有人实现了 Mixin 模式,把需要重用的代码抽到一个独立的类里面,然后令所有类继承都一个 Mixin 工具类,工具类通过 PHP 特有的 __set / __get / __call 等方式把需要重用的类塞到当前类里面,代码会变成这样子:

01 // 工具类
02 class Mixin {}
03 class ActiveRecord extends Mixin {}
04 class CacheBehavior extends Mixin {
05     // 重载源对象的查询方法
06     function find($self) {
07         // 通过传入参数获取原对象实例
08     }
09 }
10 // 业务类
11 class User extends ActiveRecord {}
12 class Article extends ActiveRecord {}
13 class Log extends ActiveRecord {}
14   
15 // 调用方式
16 $user = new User();
17 $user->attach(new CacheBehavior());
18 $user->find(); // 此时调用的是 CacheBehavior 的 find 方法

这样貌似解决了代码重用的问题了……且慢!你没发现这样的话所有类都必须继承 Mixin 工具类吗?如果某天需要用上一个不 Mixin 的 ActiveRecord 那岂不是需要把它复制一份?
于是这里就需要 trait 语法的粉墨登场了!先把 CacheBehavior 变成 trait,代码变成这样:

01 // 工具 trait
02 trait CacheBehavior {
03     function find() {}
04 }
05 // 工具类
06 class ActiveRecord {}
07 // 业务类
08 class User extends ActiveRecord {
09     use CacheBehavior;
10 }
11 class Article extends ActiveRecord {
12     use CacheBehavior;
13 }
14 class Log extends ActiveRecord {}

这样就实现了刚才使用了 Mixin 工具类才能实现的效果,代码量更少更简洁!
进一步思考,其实 ActiveRecord 也属于工具类而不是业务类(领域模型),那实际上也是应该拿出来的,于是最后代码写成了:

01 // 工具 trait
02 trait ActiveRecord {}
03 trait CacheBehavior {
04     function find() {}
05 }
06 // 业务类
07 class User {
08     use ActiveRecord, CacheBehavior;
09 }
10 class Article {
11     use ActiveRecord, CacheBehavior;
12 }
13 class Log {
14     use ActiveRecord;
15 }
16   
17 // 调用方式
18 $user = new User();
19 $user->find(); // 此时调用的是 CacheBehavior 的 find 方法,省略了 attach 步骤

代码终于和谐了!当然,ActiveRecord 和 CacheBehavior 之间的关联性还有待解决,不过这里就不纠结这个问题了=v=b
使用 trait 之后,某天出现了一个新的业务类 Manager 也只需轻松继承或 use 一下即可:

01 // 这样
02 class User {
03     use ActiveRecord, CacheBehavior;
04 }
05 class Manager extends User {}
06 // 或者
07 class Manager {
08     use ActiveRecord, CacheBehavior;
09 }
10   
11 // 直接调用
12 $manager = new Manager();
13 $manager->find(); // 同样是使用 CacheBehavior 的 find 方法

从此对“水平复用”代码表示毫无鸭梨!
更多说明请查看官方 wiki:https://wiki.php.net/rfc/horizontalreuse

<!-- .entry-content -->
分享到:
评论
1 楼 zdk2116 2012-03-01  
我觉得你说的这些可以总结为一点:就是为了解决一个多继承的问题。
你说的有点复杂了。

相关推荐

    php5.4中文手册

    1. **短数组语法**:在PHP5.4中,数组定义的语法得到了简化,可以使用`[]`代替`array()`创建数组,如`$arr = [1, 2, 3];` 2. **Traits**:这是一种代码重用机制,类似于其他语言中的“混入”或“多重继承”。Traits...

    PHP5.4源码包

    PHP5.4开始支持更简洁的数组定义语法,如`[元素1, 元素2]`,这使得代码看起来更加简洁,与现代编程语言更一致。 4. **闭包的改进** 在PHP5.4中,闭包(匿名函数)的使用更为方便,可以捕获外部变量并使用`use`...

    php 5.4 中文手册 chm 绝对可以用的!

    《PHP 5.4中文手册》是一份详细记录了PHP 5.4版本核心特性和功能的参考文档,特别适合正在学习或使用PHP 5.4的开发者们查阅。这份CHM(Compiled HTML Help)格式的手册,以其方便的检索和离线阅读特性,为程序员提供...

    PHP5.4操作文档说明

    3. **短数组语法**:PHP5.4对数组定义的语法进行了简化,允许使用`[]`来创建数组,使得代码更加简洁。例如,`$arr = [];` 和 `$arr = array();` 现在是等价的。 4. **闭包函数的改进**:在PHP5.4中,闭包函数有了更...

    php_redis.dll文件,php5.4版本

    描述中的"php5.4版本"指的是这个php_redis.dll文件是为PHP 5.4版本编译和优化的。PHP 5.4是PHP语言的一个重要版本,它在2012年发布,引入了许多新特性和性能改进,例如:Traits(类似多重继承的功能)、短数组语法、...

    php5.4.4的源码

    3. ** Short Array Syntax **:PHP 5.4引入了更简洁的数组声明语法,`[]`替代了之前的`array()`,使得代码更加简洁易读。 4. ** Closure 函数绑定(Closure function binding)**:提供了`use`关键字,允许闭包函数...

    对于PHP 5.4 你必须要知道的

    PHP 5.4是PHP语言的一次重大更新,在这次更新中,PHP在性能、安全性和可用性方面都实现了显著的改进。本知识点将详细介绍PHP 5.4的主要改进和新增特性。 首先,PHP 5.4实现了性能的大幅提升,其执行速度在某些情况...

    php各版本下载地址.doc

    在PHP 5.4中, Trait 的实现使得类间的方法复用变得更加灵活。此外,这个版本引入了Traits、匿名函数、简化的数组定义以及 Traits 的支持。同时,`__DIR__`和`__TRAIT__`魔术常量也被添加进来。你可以通过官方镜像...

    php-5.4.11

    2. Trait支持:PHP 5.4引入了Trait,这是一种代码重用机制,类似于Java的接口,可以解决单继承的局限性,提高代码复用率。 3. Short array syntax:新的简洁数组语法`[]`取代了`array()`,使得代码更加简洁易读。 ...

    php-5.4.28.tar.gz

    1. **PHP 5.4 版本**:这是PHP的一个重要版本,发布于2013年,引入了许多新特性,如 Trait(类型)支持,用于代码重用,增强了面向对象编程;Short array syntax([]代替array()创建数组),使得语法更简洁;以及...

    php代码-代码的复用:trait

    1. **定义**:Trait是PHP 5.4版本引入的一个代码复用机制,它允许开发者在一个类中定义一组方法,然后在其他类中通过`use`关键字引入这些方法。 2. **目的**:Trait的主要目的是解决单继承限制下,类之间的功能重叠...

    php-5.4.0alpha1.tar.zip

    3. **Short array syntax**:5.4版引入了短数组语法,使得声明数组变得更简洁,如`$arr = [1, 2, 3];`代替了旧的`$arr = array(1, 2, 3);`,提高了代码可读性。 4. **__DIR__魔术常量**:现在可以直接通过`__DIR__`...

    php-5.4.0.tar.gz

    PHP 5.4开始尝试将错误处理转换为异常处理,部分致命错误会抛出异常,方便开发者使用异常处理机制来捕获和处理错误。 ### 5. 其他改进 #### 5.1. 新的内建函数 例如:`array dereferencing`允许直接在数组表达式中...

    ThinkPHP5为API开发而设计的高性能PHP框架

    PHP 5.4引入了许多改进,如 Trait 支持、短数组语法以及更好的错误处理,这些特性使得代码更加简洁且易于维护。 在设计模式上,ThinkPHP5深入强化了Controller、Business、Data(CBD)模式。这种模式将业务逻辑、...

    PHP中的traits简单使用实例

    PHP 5.4中的traits,是新引入的特性,中文还真不知道如何准确翻译好。其实际的目的,是为了有的场合想用多继承,但PHP又没多继承,于是就发明了这样的一个东西。  Traits可以理解为一组能被不同的类都能调用到的...

    PHP5各个版本的新功能和新特性总结

    此外,PHP5.4也包含了一些语法上的小改进和其他细节修改。 ### PHP5.5的新特性: #### 1. yield关键字: `yield`关键字允许开发者编写生成器(generator)函数,它与迭代器类似,但不需要存储整个迭代序列于内存中...

Global site tag (gtag.js) - Google Analytics