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 根据IP地址控制访问的代码
Apr 22 PHP
php开启安全模式后禁用的函数集合
Jun 26 PHP
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
Apr 28 PHP
深入PHP操作MongoDB的技术总结
Jun 02 PHP
使用php 获取时间今天明天昨天时间戳的详解
Jun 20 PHP
php中如何使对象可以像数组一样进行foreach循环
Aug 09 PHP
PHP exif扩展方法开启详解
Jul 28 PHP
ThinkPHP实现ajax仿官网搜索功能实例
Dec 02 PHP
PHP使用递归算法无限遍历数组示例
Jan 13 PHP
PHP空值检测函数与方法汇总
Nov 19 PHP
PHP实现基于PDO扩展连接PostgreSQL对象关系数据库示例
Mar 31 PHP
PHP的mysqli_stmt_init()函数讲解
Jan 24 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
《星际争霸》各版本雷兽特点图文解析 雷兽不同形态一览
2020/03/02 星际争霸
PHP5 的对象赋值机制介绍
2011/08/02 PHP
CSS和JS标签style属性对照表(方便js开发的朋友)
2010/11/11 Javascript
Javascript 闭包引起的IE内存泄露分析
2012/05/23 Javascript
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
点击弹出层外区域关闭弹出层jquery特效示例
2013/08/25 Javascript
div模拟选择框示例代码
2013/11/03 Javascript
js中apply方法的使用详细解析
2013/11/04 Javascript
jquery html动态添加的元素绑定事件详解
2016/05/24 Javascript
关于AngularJS中ng-repeat不更新视图的解决方法
2018/09/30 Javascript
jQuery 获取除某指定对象外的其他对象 ( :not() 与.not())
2018/10/10 jQuery
谈谈为什么你的 JavaScript 代码如此冗长
2019/01/30 Javascript
Vue实现购物车详情页面的方法
2019/08/20 Javascript
关于vue利用postcss-pxtorem进行移动端适配的问题
2019/11/20 Javascript
vue+elementUI中表格高亮或字体颜色改变操作
2020/11/02 Javascript
[01:06]DOTA2亚洲邀请赛专属珍藏-荧煌之礼
2017/03/24 DOTA
python xml解析实例详解
2016/11/14 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
基于python实现自动化办公学习笔记(CSV、word、Excel、PPT)
2019/08/06 Python
pygame实现贪吃蛇游戏(上)
2019/10/29 Python
在notepad++中实现直接运行python代码
2019/12/18 Python
python实现Pyecharts实现动态地图(Map、Geo)
2020/03/25 Python
浅谈Django中的QueryDict元素为数组的坑
2020/03/31 Python
用CSS3的box-reflect来制作倒影效果
2016/11/15 HTML / CSS
法国一家多品牌成衣精品中/高档商店:Graduate Store
2019/08/28 全球购物
动态密码技术
2012/10/18 面试题
大学生村官工作感言
2014/01/10 职场文书
圣诞节红领巾广播稿
2014/02/03 职场文书
模范教师事迹材料
2014/02/10 职场文书
团队经理竞聘书
2014/03/31 职场文书
拆迁委托协议书
2014/09/15 职场文书
会计试用期工作总结2015
2015/05/28 职场文书
无犯罪记录证明样本
2015/06/16 职场文书
导游词之黄帝陵景区
2019/09/16 职场文书
django学习之ajax post传参的2种格式实例
2021/05/14 Python
Java生成读取条形码和二维码的简单示例
2021/07/09 Java/Android