require
PHP >= 5.4.0
介绍
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
以上来自 php.net 官方给出的介绍,地址为:http://php.net/manual/zh/language.oop5.traits.php
个人理解
Trait 其实是一个细粒度更细的代码复用方式,较之前的类设计逻辑,如果类 A 和 类 B 都存在这个方法,那么我们可以通过继承一个父类来实现代码复用。如果类 A 和 类 B 是父类的衍生子类倒也是没有问题,但是如果类 A 和 类 B 毫无相关的,他们唯一相似的就是有一个共同的 method ,这种情况下,A 和 B 共同继承一个父类就显得过度设计啦。所以,在这这种情况下,Trait 诞生了,它就是解决此类问题的。说的有些抽象,下面来看具体的实例:
- 传统方法
类 A :
<?php
class A {
public function eat () {
echo '我有吃的技能';
}
public function ha () {
//...
}
}
类 B :
<?php
class B {
public function eat () {
echo '我有吃的技能';
}
public function hi () {
//...
}
}
如果相同的代码出现两次,就要考虑 DRY 啦,所以这里我们可以:
<?php
class P {
public function eat () {
echo '我有吃的技能';
}
}
class A extends P {
public function ha () {
//...
}
}
class B extends P {
public function hi () {
//...
}
}
代码复用问题是解决了,但是如果 A 是美国队长,B 是蚂蚁,虽然他们都可以吃,但是这样继承真的好吗?显然是有点勉强的。
- Trait 方法
Eat Trait:
<?php
trait Eat {
public function eat () {
echo '我有吃的技能';
}
}
<?php
class A {
use Eat;
public function ha () {
//...
}
}
class B {
use Eat;
public function hi () {
//...
}
}
我们将一些公用的方法定义在 Trait 文件中,在需要使用的时候 use traitName
就可以,既解决了代码复用的问题,也避免了勉强的父类继承问题。
定义 Trait
和定义类基本相同,只是将 class 换成了 trait
<?php
trait TraitName {
public function demo () {
//...
}
}
使用 Trait
Trait 的使用也非常简单,通过 use 语句引入就可以啦,如下:
<?php
trait DemoTrait {
public function demo () {
echo 'demo';
}
}
class A {
use DemoTrait;
public function printer () {
echo __METHOD__;
}
}
$a = new A();
$a->demo();
多个 Trait 使用
use Trait1,Trait2;
Trait 注意点
一、优先级
Trait 方法 > extends 方法 > 类方法二、Trait 方法名冲突的解决
如下面的情况:
<?php
trait ta {
public function demo () {
echo 'ta';
}
}
trait tb {
public function demo () {
echo 'tb';
}
}
class A {
use ta,tb;
}
$a = new A();
$a->demo();
运行会报错:
PHP Fatal error: Trait method demo has not been applied, because there are collisions with other trait methods on A
Trait 方法名冲突了,解决方法有下:
- insteadof
class A {
use ta,tb {
tb::demo insteadof ta;
}
}
运行结果:
tb
tb::demo insteadof ta
这句代码的意思就是用 tb
中的 demo
方法替代 ta
中的 demo
方法。
Thinkphp5 Trait 的使用
thinkphp/library/think/Controller.php
:
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
\think\Loader::import('controller/Jump', TRAIT_PATH, EXT);
use think\exception\ValidateException;
class Controller
{
use \traits\controller\Jump;
//...
}
thinkphp/library/traits/controller/Jump.php
:
<?php
/**
* 用法:
* load_trait('controller/Jump');
* class index
* {
* use \traits\controller\Jump;
* public function index(){
* $this->error();
* $this->redirect();
* }
* }
*/
namespace traits\controller;
use think\Config;
use think\exception\HttpResponseException;
use think\Request;
use think\Response;
use think\response\Redirect;
use think\Url;
use think\View as ViewTemplate;
trait Jump
{
/**
* 操作成功跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function success($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
{
//... 省略代码
}
/**
* 操作错误跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
{
//... 省略代码
}
// ...
}
从上面可以看到,Thinkphp5 提供的 success()
和 error()
方法都写在这个 Trait 文件中,那么我们就可以不通过继承 think\Controller
来获取这两个方法,直接 use \traits\controller\Jump;
就可以啦。
好了,今天的教程就到这里啦。本着快速学习的目的,本教程不会过多深入。如果想深入学习可以联系作者哦!
这是小滕的《Thinkphp5入门系列课程》第四课:Trait 使用。
喜欢的给个订阅呗!