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实现Ftp用户的在线管理的代码
Mar 06 PHP
PHP 数字左侧自动补0
Mar 31 PHP
php HandlerSocket的使用
May 02 PHP
PHP中用hash实现的数组
Jul 17 PHP
20个PHP常用类库小结
Sep 11 PHP
PHP框架Swoole定时器Timer特性分析
Aug 19 PHP
php打包网站并在线压缩为zip
Feb 13 PHP
PHP中类的自动加载的方法
Mar 17 PHP
PHP使用栈解决约瑟夫环问题算法示例
Aug 27 PHP
Yii框架引入coreseek分页功能示例
Feb 08 PHP
PHP使用DOM对XML解析处理操作示例
Jul 04 PHP
浅谈PHP7中的一些小技巧
May 29 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
如何去掉文章里的 html 语法
2006/10/09 PHP
PHP 过滤页面中的BOM(实现代码)
2013/06/29 PHP
PHP 数组基本操作小结(推荐)
2016/06/13 PHP
PHP回调函数简单用法示例
2019/05/08 PHP
jscript之Read an Excel Spreadsheet
2007/06/13 Javascript
根据对象的某一属性进行排序的js代码(如:name,age)
2010/08/10 Javascript
THREE.JS入门教程(4)创建粒子系统
2013/01/24 Javascript
浅析js中取绝对值的2种方法
2013/07/09 Javascript
使用js正则控制input标签只允许输入的值
2013/07/29 Javascript
jquery等待效果示例
2014/05/01 Javascript
js面向对象编程总结
2017/02/16 Javascript
react-router实现按需加载
2017/05/09 Javascript
基于vue2框架的机器人自动回复mini-project实例代码
2017/06/13 Javascript
详解使用nvm管理多版本node的方法
2017/08/30 Javascript
微信小程序顶部可滚动导航效果
2017/10/31 Javascript
使用vue编写h5公众号跳转小程序的实现代码
2020/11/27 Vue.js
[01:31:03]DOTA2完美盛典全回顾 见证十五项大奖花落谁家
2017/11/28 DOTA
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python2.x版本中maketrans()方法的使用介绍
2015/05/19 Python
Python 的内置字符串方法小结
2016/03/15 Python
python数组循环处理方法
2019/08/26 Python
关于python 的legend图例,参数使用说明
2020/04/17 Python
Python 在函数上添加包装器
2020/07/28 Python
pycharm中leetcode插件使用图文详解
2020/12/07 Python
含精油的天然有机化妆品:Indemne
2019/08/27 全球购物
路德维希•贝克(LUDWIG BECK)中文官网:德国大型美妆百货
2020/09/19 全球购物
怎样声明子类
2013/07/02 面试题
国家助学金获奖感言
2014/01/31 职场文书
摄影专业毕业生求职信
2014/03/13 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
好学生评语大全
2014/05/05 职场文书
个人投资合作协议书
2014/10/12 职场文书
2015年宣传部部长竞选演讲稿
2014/11/28 职场文书
《我在为谁工作》:工作的质量往往决定生活的质量
2019/12/27 职场文书
java executor包参数处理功能 
2022/02/15 Java/Android
vscode远程免密登入Linux服务器的配置方法
2022/06/28 Servers