PHP中trait使用方法详细介绍


Posted in PHP onMay 21, 2017

说通俗点,PHP中使用trait关键字是为了解决一个类既想集成基类的属性和方法,又想拥有别的基类的方法,而trait一般情况下是和use搭配使用的。

<?php
  trait Drive {
    public $carName = 'trait';
    public function driving() {
      echo "driving {$this->carName}\n";
    }
  }
  class Person {
    public function eat() {
      echo "eat\n";
    }
  }
  class Student extends Person {
    use Drive;
    public function study() {
      echo "study\n";
    }
  }
  $student = new Student();
  $student->study();
  $student->eat();
  $student->driving();

?>

输出结果如下:

study
eat
driving trait

上面的例子中,Student类通过继承Person,有了eat方法,通过组合Drive,有了driving方法和属性carName。

如果Trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?

<?php 
  trait Drive {
    public function hello() {
      echo "hello drive\n";
    }
    public function driving() {
      echo "driving from drive\n";
    }
  }
  class Person {
    public function hello() {
      echo "hello person\n";
    }
    public function driving() {
      echo "driving from person\n";
    }
  }
  class Student extends Person {
    use Drive;
    public function hello() {
      echo "hello student\n";
    }
  }
  $student = new Student();
  $student->hello();
  $student->driving();
?>

输出结果如下:

hello student
driving from drive

因此得出结论:当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。

如果要组合多个Trait,通过逗号分隔 Trait名称:

use Trait1, Trait2;

如果多个Trait中包含同名方法或者属性时,会怎样呢?答案是当组合的多个Trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。

<?php
trait Trait1 {
  public function hello() {
    echo "Trait1::hello\n";
  }
  public function hi() {
    echo "Trait1::hi\n";
  }
}
trait Trait2 {
  public function hello() {
    echo "Trait2::hello\n";
  }
  public function hi() {
    echo "Trait2::hi\n";
  }
}
class Class1 {
  use Trait1, Trait2;
}
?>

输出结果如下:

PHP Fatal error:  Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in ~/php54/trait_3.php on line 20

使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法请看代码:

<?php
trait Trait1 {
  public function hello() {
    echo "Trait1::hello\n";
  }
  public function hi() {
    echo "Trait1::hi\n";
  }
}
trait Trait2 {
  public function hello() {
    echo "Trait2::hello\n";
  }
  public function hi() {
    echo "Trait2::hi\n";
  }
}
class Class1 {
  use Trait1, Trait2 {
    Trait2::hello insteadof Trait1;
    Trait1::hi insteadof Trait2;
  }
}
class Class2 {
  use Trait1, Trait2 {
    Trait2::hello insteadof Trait1;
    Trait1::hi insteadof Trait2;
    Trait2::hi as hei;
    Trait1::hello as hehe;
  }
}
$Obj1 = new Class1();
$Obj1->hello();
$Obj1->hi();
echo "\n";
$Obj2 = new Class2();
$Obj2->hello();
$Obj2->hi();
$Obj2->hei();
$Obj2->hehe();
?>

输出结果如下:

Trait2::hello
Trait1::hi

Trait2::hello
Trait1::hi
Trait2::hi
Trait1::hello

as关键词还有另外一个用途,那就是修改方法的访问控制:

Trait 也能组合Trait,Trait中支持抽象方法、静态属性及静态方法,测试代码如下:

<?php
trait Hello {
  public function sayHello() {
    echo "Hello\n";
  }
}
trait World {
  use Hello;
  public function sayWorld() {
    echo "World\n";
  }
  abstract public function getWorld();
  public function inc() {
    static $c = 0;
    $c = $c + 1;
    echo "$c\n";
  }
  public static function doSomething() {
    echo "Doing something\n";
  }
}
class HelloWorld {
  use World;
  public function getWorld() {
    return 'get World';
  }
}
$Obj = new HelloWorld();
$Obj->sayHello();
$Obj->sayWorld();
echo $Obj->getWorld() . "\n";
HelloWorld::doSomething();
$Obj->inc();
$Obj->inc();
?>

输出结果如下:

Hello
World
get World
Doing something
1
2

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP下一个非常全面获取图象信息的函数
Nov 20 PHP
php结合飞信 免费天气预报短信
May 07 PHP
PHP CKEditor 上传图片实现代码
Nov 06 PHP
PHP实现数字补零功能的2个函数介绍
May 12 PHP
PHP中使用json数据格式定义字面量对象的方法
Aug 20 PHP
php 反斜杠处理函数addslashes()和stripslashes()实例详解
Dec 25 PHP
PHP 与 UTF-8 的最佳实践详细介绍
Jan 04 PHP
PHP 配置后台登录以及模板引入
Jan 24 PHP
php格式文件打开的四种方法
Feb 24 PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
Apr 27 PHP
使用Laravel中的查询构造器实现增删改查功能
Sep 03 PHP
PHP7新特性
Mar 09 PHP
php写app接口并返回json数据的实例(分享)
May 20 #PHP
PHP实现json_decode不转义中文的方法
May 20 #PHP
Yii框架参数化查询中IN查询只能查询一个的解决方法
May 20 #PHP
Yii框架使用魔术方法实现跨文件调用功能示例
May 20 #PHP
Yii框架实现的验证码、登录及退出功能示例
May 20 #PHP
利用Laravel事件系统如何实现登录日志的记录详解
May 20 #PHP
Yii框架实现图片上传的方法详解
May 20 #PHP
You might like
php实现utf-8和GB2312编码相互转换函数代码
2013/02/07 PHP
Linux系统中设置多版本PHP共存配合Nginx服务器使用
2015/12/21 PHP
php中错误处理操作实例分析
2019/08/23 PHP
javascript之对系统的toFixed()方法的修正
2007/05/08 Javascript
关于js类的定义
2011/06/28 Javascript
jQuery实现简单的DIV拖动效果
2016/02/19 Javascript
通过AngularJS实现图片上传及缩略图展示示例
2017/01/03 Javascript
vuejs+element-ui+laravel5.4上传文件的示例代码
2017/08/12 Javascript
常用的9个JavaScript图表库详解
2017/12/19 Javascript
vue.js轮播图组件使用方法详解
2018/07/03 Javascript
图文讲解vue的v-if使用方法
2019/02/11 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
2019/09/02 Javascript
使用Angular material主题定义自己的组件库的配色体系
2019/09/04 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
Jquery+AJAX实现无刷新上传并重命名文件操作示例【PHP后台接收】
2020/05/29 jQuery
[13:21]DOTA2国际邀请赛采访专栏:RSnake战队国士无双,Fnatic.Fly
2013/08/06 DOTA
Python基于smtplib实现异步发送邮件服务
2015/05/28 Python
总结网络IO模型与select模型的Python实例讲解
2016/06/27 Python
python+selenium实现京东自动登录及秒杀功能
2017/11/18 Python
python的pip安装以及使用教程
2018/09/18 Python
selenium+python设置爬虫代理IP的方法
2018/11/29 Python
详解Python正则表达式re模块
2019/03/19 Python
教你如何编写、保存与运行Python程序的方法
2019/07/12 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
2020/11/05 Python
如何创建一个Flask项目并进行简单配置
2020/11/18 Python
canvas小画板之平滑曲线的实现
2020/08/12 HTML / CSS
J2EE中的容器都包括哪些
2013/08/21 面试题
施工资料员岗位职责
2014/01/06 职场文书
四年级语文教学反思
2014/02/05 职场文书
物理教育专业求职信
2014/06/25 职场文书
大学生翘课检讨书范文
2014/10/06 职场文书
五四青年节比赛演讲稿
2015/03/18 职场文书
大学生英文求职信范文
2015/03/19 职场文书
2015学习委员工作总结范文
2015/04/03 职场文书
学生安全责任协议书
2016/03/22 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python