为什么 PHP 会引入 Trait ? 我们先来看看软件开发中的两种常用代码复用模式,继承和组合。
- 继承:强调 父类与子类 的关系,即子类是父类的一个特殊类型;
- 组合:强调 整体与局部 的关系,侧重的一种需要的关系;
软件开发中有一条原则,叫做组合优于继承。这是因为从耦合度来看,继承要高于组合。继承关系中,子类与父类保持着高度的依赖关系,加上 PHP 不支持多继承,为了避免重写编写代码,很多功能都被统一封装到父类中。这样做有两个坏处:一是随着继承的层数和子类的增加,代码复杂度不断增加,大量的方法都将面临着重写;二是这些功能对于一些子类来说可能是不必要的,破坏了代码的封装性。
Trait 的提出弥补了 PHP 对组合支持的不足,一个 Trait 就相当于一个模块,不同的 Trait 以组合的方式注入到类中。我们以 Laravel 的控制器为例,来介绍下继承和组合是如何在具体的场景中使用的。
首先,底层的代码应当多使用组合。Laravel 的底层控制器只继承了一个简单的控制器 Illuminate\Routing\Controller
,结构相对稳定。同时,控制器使用了不同的 Trait
来组织代码,避免了对象的臃肿,极大程度的保持了架构的灵活性。
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
而具体的业务逻辑或顶层代码应当