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设计模式 注册表模式
Feb 05 PHP
Zend的MVC机制使用分析(一)
May 02 PHP
PHP防止跨域提交表单
Nov 01 PHP
php开发中的页面跳转方法总结
Apr 26 PHP
分享php代码将360浏览器导出的favdb的sqlite数据库文件转换为html
Dec 09 PHP
php获取文件后缀的9种方法
Mar 22 PHP
PHP版单点登陆实现方案的实例
Nov 17 PHP
php微信开发之自定义菜单实现
Nov 18 PHP
php插入含有特殊符号数据的处理方法
Nov 24 PHP
PHP微信H5支付开发实例
Jul 25 PHP
php中青蛙跳台阶的问题解决方法
Oct 14 PHP
PHP array_reduce()函数的应用解析
Oct 28 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
swfupload 多文件上传实现代码
2008/08/27 PHP
php面向对象全攻略 (十) final static const关键字的使用
2009/09/30 PHP
PHP的array_diff()函数在处理大数组时的效率问题
2011/11/27 PHP
PHP实现的网站目录扫描索引工具
2016/09/08 PHP
thinkphp分页集成实例
2017/07/24 PHP
yii2.0整合阿里云oss的示例代码
2017/09/19 PHP
PHP实现文件上传操作和封装
2020/03/04 PHP
对google个性主页的拖拽效果的js的完整注释[转]
2007/04/10 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
jQuery验证Checkbox是否选中的代码 推荐
2011/09/04 Javascript
IE网页js语法错误2行字符1、FF中正常的解决方法
2013/09/09 Javascript
如何判断鼠标是否在DIV的区域内
2013/11/13 Javascript
jQuery判断一个元素是否可见的方法
2015/06/05 Javascript
javascript获取网页宽高方法汇总
2015/07/19 Javascript
基于jPlayer三分屏的制作方法
2016/12/21 Javascript
详解Vue-cli 创建的项目如何跨域请求
2017/05/18 Javascript
利用Vue.js实现求职在线之职位查询功能
2017/07/03 Javascript
微信小程序点餐系统开发常见问题汇总
2019/08/06 Javascript
JavaScript实现简单计算器功能
2019/12/19 Javascript
JS绘图Flot应用图形绘制异常解决方案
2020/10/16 Javascript
[06:09]辉夜杯主赛事开幕式
2015/12/25 DOTA
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
2016/01/20 Python
python二进制文件的转译详解
2019/07/03 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
Django自带的用户验证系统实现
2020/12/18 Python
娇韵诗加拿大官网:Clarins加拿大
2017/11/20 全球购物
Moda Operandi官网:美国奢侈品电商,海淘秀场T台同款
2020/05/26 全球购物
初始化了一个没有run()方法的线程类,是否会出错?
2014/03/27 面试题
大学生如何写自荐信
2014/01/08 职场文书
优质护理服务演讲稿
2014/05/07 职场文书
2014高中生入党思想汇报范文
2014/09/13 职场文书
个人查摆问题整改措施
2014/10/04 职场文书
2015年调度员工作总结
2015/04/30 职场文书
2019年图书室自查报告范本
2019/10/12 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL
Python类方法总结讲解
2021/07/26 Python