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的日期与时间函数技巧
Apr 24 PHP
深入PHP magic quotes的详解
Jun 17 PHP
Codeigniter出现错误提示Error with CACHE directory的解决方案
Jun 12 PHP
Laravel 4 初级教程之Pages、表单验证
Oct 30 PHP
ThinkPHP在新浪SAE平台的部署实例
Oct 31 PHP
php简单判断文本编码的方法
Jul 30 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
Oct 10 PHP
PHP实现导出excel数据的类库用法示例
Oct 15 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
Aug 30 PHP
PHP实现的字符串匹配算法示例【sunday算法】
Dec 19 PHP
实例讲解PHP页面静态化
Feb 05 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
Mar 23 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 中关于ord($str)&amp;gt;0x80的详细说明
2012/09/23 PHP
PHP遍历数组的三种方法及效率对比分析
2015/02/12 PHP
php使用curl出现Expect:100-continue解决方法
2015/03/03 PHP
PHP基于简单递归函数求一个数阶乘的方法示例
2017/04/26 PHP
iframe自适应宽度、高度 ie6 7 8,firefox 3.86下测试通过
2010/07/29 Javascript
讨论html与javascript在浏览器中的加载顺序问题
2013/11/27 Javascript
JS实现局部选择打印和局部不选择打印
2014/04/03 Javascript
用js格式化金额可设置保留的小数位数
2014/05/09 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
2015/04/12 Javascript
限制只能输入数字的实现代码
2016/05/16 Javascript
实现JavaScript高性能的数据存储
2016/12/11 Javascript
JS数组搜索之折半搜索实现方法分析
2017/03/27 Javascript
利用ES6的Promise.all实现至少请求多长时间的实例
2017/08/28 Javascript
Node.js自定义实现文件路由功能
2017/09/22 Javascript
jQuery实现的淡入淡出与滑入滑出效果示例
2018/04/18 jQuery
layui的table中显示图片方法
2018/08/17 Javascript
angular5 子组件监听父组件传入值的变化方法
2018/09/30 Javascript
nodejs对项目下所有空文件夹创建gitkeep的方法
2019/08/02 NodeJs
小程序实现日历左右滑动效果
2019/10/21 Javascript
vue项目前端微信JSAPI与外部H5支付相关实现过程及常见问题
2020/04/14 Javascript
Python文件和流(实例讲解)
2017/09/12 Python
神经网络python源码分享
2017/12/15 Python
python pandas 对series和dataframe的重置索引reindex方法
2018/06/07 Python
Python动态赋值的陷阱知识点总结
2019/03/17 Python
英国最大的手表网站:The Watch Hut
2017/03/31 全球购物
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
采购主管的岗位职责
2013/12/17 职场文书
人力资源经理自我评价
2014/01/04 职场文书
乡镇庆八一活动方案
2014/02/02 职场文书
校庆标语集锦
2014/06/25 职场文书
2014年房地产销售工作总结
2014/12/01 职场文书
全国爱牙日活动总结
2015/02/05 职场文书
公务员年度考核登记表个人总结
2015/02/12 职场文书
PHP实现创建以太坊钱包转账等功能
2021/04/21 PHP
Python+Appium自动化测试的实战
2021/06/30 Python
面试中canvas绘制图片模糊图片问题处理
2022/03/13 Javascript