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面向对象全攻略 (二) 实例化对象 使用对象成员
Sep 30 PHP
PHP is_dir() 判断给定文件名是否是一个目录
May 10 PHP
PHP UTF8中文字符截断函数代码
Sep 11 PHP
PHP strstr 函数判断字符串是否否存在的实例代码
Sep 28 PHP
php中Array2xml类实现数组转化成XML实例
Dec 08 PHP
php实现字符串首字母转换成大写的方法
Mar 17 PHP
php数字运算验证码的实现代码
Jul 30 PHP
PHP判断手机是IOS还是Android
Dec 09 PHP
PHP使用curl制作简易百度搜索
Nov 03 PHP
PHP创建自己的Composer包方法
Apr 09 PHP
PHP7中I/O模型内核剖析详解
Apr 14 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
一个简单的PHP投票程序源码
2007/03/11 PHP
php 保留小数点
2009/04/21 PHP
php中in_array函数用法探究
2014/11/25 PHP
php上传大文件设置方法
2016/04/14 PHP
php实现PDO中捕获SQL语句错误的方法
2017/02/16 PHP
jQuery判断元素是否是隐藏的代码
2011/04/24 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
基于jquery实现三级下拉菜单
2016/05/10 Javascript
js对字符串进行编码的方法总结(推荐)
2016/11/10 Javascript
Bootstrap框架实现广告轮播效果
2016/11/28 Javascript
nodejs处理图片的中间件node-images详解
2017/05/08 NodeJs
javascript中的相等操作符(==与===区别)
2019/12/21 Javascript
Python 自动补全(vim)
2014/11/30 Python
Python类的定义、继承及类对象使用方法简明教程
2015/05/08 Python
python中管道用法入门实例
2015/06/04 Python
Python中 Lambda表达式全面解析
2016/11/28 Python
Python中分支语句与循环语句实例详解
2018/09/13 Python
对Python发送带header的http请求方法详解
2019/01/02 Python
python判断字符串或者集合是否为空的实例
2019/01/23 Python
Python利用matplotlib做图中图及次坐标轴的实例
2019/07/08 Python
使用pandas读取文件的实现
2019/07/31 Python
python 子类调用父类的构造函数实例
2020/03/12 Python
PyQt5 如何让界面和逻辑分离的方法
2020/03/24 Python
html5的画布canvas——画出简单的矩形、三角形实例代码
2013/06/09 HTML / CSS
用canvas画心电图的示例代码
2018/09/10 HTML / CSS
美国Rue La La闪购网站:奢侈品、中高档品牌限时折扣
2016/10/19 全球购物
阿提哈德航空官方网站:Etihad Airways
2017/01/06 全球购物
Raleigh兰令自行车美国官网:英国凤头牌自行车
2018/01/08 全球购物
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
泰国国际航空公司官网:Thai Airways International
2019/12/04 全球购物
Java面试题:说出如下代码的执行结果
2015/10/30 面试题
教师实习自我鉴定
2013/12/13 职场文书
廉洁校园实施方案
2014/05/25 职场文书
2014年安全管理工作总结
2014/12/01 职场文书
2014年小学教研工作总结
2014/12/06 职场文书
SQL Server中的游标介绍
2022/05/20 SQL Server