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写的serv-u的web申请账号的程序
Oct 09 PHP
php 中英文语言转换类
Sep 07 PHP
PHP goto语句简介和使用实例
Mar 11 PHP
PHP中的Memcache详解
Apr 05 PHP
php中mail函数发送邮件失败的解决方法
Dec 24 PHP
wampserver改变默认网站目录的办法
Aug 05 PHP
以实例全面讲解PHP中多进程编程的相关函数的使用
Aug 18 PHP
PHP.vs.JAVA
Apr 29 PHP
PHP实现网页内容html标签补全和过滤的方法小结【2种方法】
Apr 27 PHP
PHP实现APP微信支付的实例讲解
Feb 10 PHP
php+ajax实现文件切割上传功能示例
Mar 03 PHP
利用PHP计算有多少小于当前数字的数字方法示例
Aug 26 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 MYSQL乱码问题,使用SET NAMES utf8校正
2009/11/30 PHP
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
PHP的MVC模式实现原理分析(一相简单的MVC框架范例)
2014/04/29 PHP
Ajax::prototype 源码解读
2007/01/22 Javascript
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
有道JavaScript监听浏览器的问题
2010/06/23 Javascript
读jQuery之十一 添加事件核心方法
2011/07/31 Javascript
点击页面其它地方隐藏该div的两种思路
2013/11/18 Javascript
jquery获取当前点击对象的value方法
2014/02/28 Javascript
node+express+ejs制作简单页面上手指南
2014/11/26 Javascript
HTML,CSS,JavaScript速查表推荐
2014/12/02 Javascript
jQuery on方法传递参数示例
2014/12/09 Javascript
JavaScript实现鼠标滑过图片变换效果的方法
2015/04/16 Javascript
写给小白的JavaScript引擎指南
2015/12/04 Javascript
jQuery插件之Tocify动态节点目录菜单生成器附源码下载
2016/01/08 Javascript
Jquery调用iframe父页面中的元素及方法
2016/08/23 Javascript
完全深入学习Bootstrap表单
2016/11/28 Javascript
Javascript之深入浅出prototype
2017/02/06 Javascript
nodejs+express搭建多人聊天室步骤
2018/02/12 NodeJs
详解Vue单元测试case写法
2018/05/24 Javascript
JS实现匀速与减速缓慢运动的动画效果封装示例
2018/08/27 Javascript
vue项目在线上服务器访问失败原因分析
2020/08/14 Javascript
Jquery 获取相同NAME 或者id删除行操作
2020/08/24 jQuery
[04:19]DOTA2亚洲邀请赛 现场花絮
2015/03/11 DOTA
Python编程把二叉树打印成多行代码
2018/01/04 Python
python中pylint使用方法(pylint代码检查)
2018/04/06 Python
selenium+python自动化测试环境搭建步骤
2019/06/03 Python
Django网络框架之创建虚拟开发环境操作示例
2019/06/06 Python
python如何删除文件中重复的字段
2019/07/16 Python
Python笔试面试题小结
2019/09/07 Python
科茨沃尔德家居商店:Scotts of Stow
2018/06/29 全球购物
RetroStage德国:复古服装
2019/02/03 全球购物
爱心捐款感谢信
2015/01/20 职场文书
初三数学教学反思
2016/02/17 职场文书
OpenCV-Python实现人脸磨皮算法
2021/06/07 Python
mysql中整数数据类型tinyint详解
2021/12/06 MySQL