PHP中的Traits用法详解
PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法。php的Traits和Go语言的组合功能有点类似,
通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化。具体用法请看下面的代码:
<?php trait Drive {public $carName = 'BMW';public function driving() {echo "driving {$this->carName}\n";} } class Person {public function age() {echo "i am 18 years old\n";} } class Student extends Person {use Drive;public function study() {echo "Learn to drive \n";} } $student = new Student(); $student->study(); $student->age(); $student->driving();
Learn to drive i am 18 years old driving BMW
上面的例子中,Student类通过继承Person,有了age方法,通过组合Drive,有了driving方法和属性carName。
如果Trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?通过下面的代码测试一下:
<?php trait Drive {public function hello() {echo "hello 周伯通\n";}public function driving() {echo "周伯通不会开车\n";} } class Person {public function hello() {echo "hello 大家好\n";}public function driving() {echo "大家都会开车\n";} } class Student extends Person {use Drive;//trait 的方法覆盖了基类Person中的方法,所以Person中的hello 和driving被覆盖public function hello() {echo "hello 新学员\n";//当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,所以此处hello会覆盖trait中的hello } } $student = new Student(); $student->hello(); $student->driving();
hello 新学员 周伯通不会开车
因此得出结论:当方法或属性同名时,当前类中的方法会覆盖 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; }//输出:Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in
使用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关键词还有另外一个用途,那就是修改方法
的访问控制:
<?php trait Hello {public function hello() {echo "hello,我是周伯通\n";} } class Class1 {use Hello {hello as protected;} } class Class2 {use Hello {Hello::hello as private hi;} } $Obj1 = new Class1(); $Obj1->hello(); # 报致命错误,因为hello方法被修改成受保护的 $Obj2 = new Class2(); $Obj2->hello(); # 输出: hello,我是周伯通,因为原来的hello方法仍然是公共的 $Obj2->hi(); # 报致命错误,因为别名hi方法被修改成私有的
Uncaught Error: Call to protected method Class1::hello() from context '' in D:\web\mytest\p.php:18
Trait 也能组合Trait,Trait中支持抽象方法、静态属性及静态方法,测试代码如下:
<?php trait Hello {public function sayHello() {echo "Hello 我是周伯通\n";} } trait World {use Hello;public function sayWorld() {echo "hello 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 'do you get World ?';} } $Obj = new HelloWorld(); $Obj->sayHello(); $Obj->sayWorld(); echo $Obj->getWorld() . "\n"; HelloWorld::doSomething(); $Obj->inc(); $Obj->inc();
Hello 我是周伯通 hello world do you get World ? Doing something 1 2
PHP中的Traits用法详解相关推荐
- C++中substr()函数用法详解
C++中substr()函数用法详解 原型: string substr (size_t pos = 0, size_t len = npos) const; 返回一个新构造的string对象,其值初 ...
- c++中vector的用法详解
c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...
- C#中NameValueCollection类用法详解
C#中NameValueCollection类用法详解,1.NameValueCollection类集合是基于 NameObjectCollectionBase 类. 但与 NameObjectCol ...
- c++ memset 语言_C++中memset函数用法详解
本文实例讲述了C++中memset函数用法.分享给大家供大家参考,具体如下: 功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,块的大小由第三个参数指定,这个函数通常 ...
- python中的super用法详解_【Python】【类】super用法详解
一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(sel ...
- JSP 中EL表达式用法详解
EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...
- java中throws用法_java中throws实例用法详解
在程序出现异常时,会有一个抛出异常的throw出现,这里我们要跟今天所讲的throws区分开.throws的作用是声明抛出,在名称上也跟throw有所不同.下面我们就throws对策概念.语法.实例带 ...
- python中的super用法详解_Python中super函数用法实例分析
本文实例讲述了python中super函数用法.分享给大家供大家参考,具体如下: 这是个高大上的函数,在python装13手册里面介绍过多使用可显得自己是高手 23333. 但其实他还是很重要的. 简 ...
- STL 中map的用法详解
STL 中map的用法详解 Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可 ...
最新文章
- macos 全局快捷键 打开 iterm_MouseInc – 完全免费的全局鼠标手势增强工具 | 马小帮...
- Tableau可视化分析实战系列Tableau基础概念全解析 (一)-数据结构及字段
- 你多久更新一次简历,决定了你的收入多久能提升
- 教学思路SQL之预备课程学习 建库、建表、建约束、关系、部分T-sql语句
- -Dmaven.multiModuleProjectDirectory system propery
- 疯狂html5+css3+javascript讲义 pdf_成为一名优秀的HTML5前端工程师需要掌握哪些技能?...
- 活动目录应用篇一:使用windows server 2008 backup备份AD是的账户权限问题
- 代理模式、动态代理及其应用
- python常用内置方法_Python3 常用的几个内置方法
- 计算1到100的整数和
- spring cloud超时时间设置
- python知识:json格式文本;异常处理;字符串处理;unicode类型和str类型转换
- 安装torchvision时,报错error: command ‘aarch64-linux-gnu-gcc‘ failed with exit status 1
- php如何用菜刀连接getshell,xise菜刀后门箱子制作:Sqlmao连接Mysql实现Getshell
- [Angular] - 01 Architecture and workflow
- 领英开发客户的思路和方法!拥有超过2万6千个领英好友后,你也能坐等流量和询盘。
- 自组网(Adhoc)和基础网(Infra)
- SCADA系统架构、类型和应用
- 数学建模选修课笔记——模糊聚类分析
- Android Sensor感应器介绍(三)获取用户移动方向,指南针原理
热门文章
- Nginx配置同一个域名同时支持http与https两种方式访问
- 展开字符串(dfs)
- total commander按文件夹大小显示
- 和菜鸟一起学android4.0.3源码之lcd屏幕背光调节
- 条码扫描二维码扫描——ZXing android 源码简化
- debugfs查看文件块号,dd命令读指定块号的内容
- Linux之fgrep命令
- 在线黑客帝国文字效果生成工具
- 关于eclipse新建web项目,提示:The superclass javax.servlet.http.HttpServlet was not found on the Java解决办法...
- 一道简单的多维数组取值问题