trait技术详解,这次包你学得会
trait的使用技巧
trait是php5.4以后新增加的一个功能,可以将多个类中,共用的一些属性和方法提取出来做来公共trait类,就像是装配汽车的配件,如果你的类中要用到这些配件,就直接用use导入就可以了,相当于把trait中的代码复制到当前类中.
因为trait不是类,所以不能有静态成员,类常量,当然也不可能被实例化。
其实一个类中的代码,可以分为二大部分:一是我们自己写的代码,暂且叫私有代码吧,还有一部分就是公共代码了,之前主要是由父类代码组成。现在你的类中的公共代码又多一个新成员:trait类代码。
如果说:继承可以纵向扩展一个类,那么trait就是横向扩展一个类功能
下面以实例进行演示:
//1创建一个trait类Test1
<?php
trait Test1
{
public $name = 'PHP中文网'; //trait类中可以用属性
public function hello1() //trait类中主要成员是方法
{
return 'Test1::hello1()';
}
}
//2.创建triat类Test2
trait Test2
{
function hello2()
{
return 'Test2::hello2()';
}
}
//3.创建Demo1类
class Demo1
{
use Test1, Test2;
}
//进行测试
$obj = new Demo1;
echo $obj->hello1(); //访问trait类Test1中的hello1()
echo '<hr>';
echo $obj->name; //访问ttrait类Test1中的$name属性
echo '<hr>';
echo $obj->hello2(); //访问ttrait类Test1中的hello2()
trait可以互相嵌套,一个trait类中可以用use导入另一个trait类,理解成代码复制就可以了.
例如本例中,在Test2中要用到Test1中的代码,我们只要改动二个地方就可以了。
一是在Test2中用use Test1;导入Test1中的代码,
二是在Demo1类中的,去掉对Test1的引用,只保留对Test2的引用,想想这是为什么?给大家当作一个思考题吧~
修改后的代码如下:
//1创建一个trait类Test1
<?php
trait Test1
{
public $name = 'PHP中文网'; //trait类中可以用属性
public function hello1() //trait类中主要成员是方法
{
return 'Test1::hello1()';
}
}
//2.创建triat类Test2
trait Test2
{
use Test1;
function hello2()
{
//在Test2中访问Test1中的属性name,注意语法与普通类是一样的
return 'Test2::hello2()'.$this->name;
}
}
//3.创建Demo1类
class Demo1
{
// use Test1, Test2;
use Test2;
}
//进行测试
$obj = new Demo1;
echo $obj->hello1(); //访问trait类Test1中的hello1()
echo '<hr>';
echo $obj->name; //访问ttrait类Test1中的$name属性
echo '<hr>';
echo $obj->hello2(); //访问ttrait类Test1中的hello2()
刚才说过,类中导入的公共代码,除了trait方法集,还可以有父类,如果在子类中访问父类中的成员,大家应该很熟悉了,现在一个类除了可以从父类继承成员,还可以从trait类中继承,那么有一个问题就不可避免了,如果父类和trait类中的成员命名冲突怎么办?说人话,就是重名了怎么办?下面我们以方法重名来演示一下处理方案。
再创建一个类Demo,做为Demo1类的父类。
//3.创建父类Demo
class Demo
{
//在父类中创建一个与Test2重名的方法hello2()
public function hello2()
{
return '父类Demo::hello2()';
}
}
代码如下:
//1创建一个trait类Test1
trait Test1
{
public $name = 'PHP中文网'; //trait类中可以用属性
public function hello1() //trait类中主要成员是方法
{
return 'Test1::hello1()';
}
}
//2.创建triat类Test2
trait Test2
{
use Test1;
function hello2()
{
//在Test2中访问Test1中的属性name,注意语法与普通类是一样的
return 'Test2::hello2()'.$this->name;
}
}
//3.创建父类Demo
class Demo
{
public function hello2()
{
return '父类Demo::hello2()';
}
}
//4.创建Demo1类
class Demo1 extends Demo
{
// use Test1, Test2;
use Test2;
}
//进行测试
$obj = new Demo1;
echo $obj->hello1(); //访问trait类Test1中的hello1()
echo '<hr>';
echo $obj->name; //访问ttrait类Test1中的$name属性
echo '<hr>';
echo $obj->hello2(); //访问ttrait类Test1中的hello2()
再次访问,会发现,结果与之前完全一样没有任何变化,父类Demo中的hello2方法好像隐身了,压根不存在一样的。事实上,父类Demo中的hello2方法当然是存在的,只是被trat类Test2中的同名方法hello2覆盖掉了,原因就是:trait类中的同名方法,访问优先级大于父类的同名方法。
如果我们就想访问父类中的hello2方法,怎么办呢?只有一个办法,要么父类方法改名,要么Test2中的方法改名,我们把Test2中的hello2方法改成hello3,再次访问,就可以看到父类的执行结果了。
那么,我们再进一点想一下,如果在子类也有一个hello2方法呢?那么结果会是什么样?
我们来试一下,在Demo1类中添加如下代码:
//4.创建Demo1类
class Demo1 extends Demo
{
// use Test1, Test2;
use Test2;
//在Demo1类中创建与Test2和父类Demo中同名的方法hello2()
public function hello2()
{
return 'Demo1::hello()';
}
}
在浏览器再次方法,果然不出所料,子类Demo1中的hello2方法的执行结果覆盖掉了Test2中的同名方法
现在我们总结一下在同一个类中,同名方法的优先级:子类>Trait类>父类,与就是说,谁离调用者越近,谁的优先级就越高。
下面我们再讨论最后一个问题:如果trait类中方法重名了,怎么办?如果是trait类中被所有类共享的方法集,重名的可能性是非常大的。
下面我们修改一下代码,删除一些用不到代码:
//1创建一个trait类Test1
trait Test1
{
public function hello()
{
return 'Test1::hello()';
}
}
//2.创建triat类Test2
trait Test2
{
function hello()
{
return 'Test2::hello()';
}
}
//3.创建类Demo
class Demo
{
use Test1, Test2{
//用Test1中的hello()方法替代Test2中的同名方法
Test1::hello insteadof Test2;
//Test2中的hello()方法用别名访问
Test2::hello as test2Hello;
} //这里千万不要加分号 ;
} //进行测试
$obj = new Demo;
echo $obj->hello(); //访问Test1中的hello()
echo '<hr>';
echo $obj->test2Hello();//别名访问Test2中的hello()
trait技术详解,这次包你学得会的更多相关文章
- Windows驱动——读书笔记《Windows驱动开发技术详解》
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- Comet技术详解:基于HTTP长连接的Web端实时通信技术
前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...
- Protocol Buffer技术详解(Java实例)
Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...
- Protocol Buffer技术详解(语言规范)
Protocol Buffer技术详解(语言规范) 该系列Blog的内容主体主要源自于Protocol Buffer的官方文档,而代码示例则抽取于当前正在开发的一个公司内部项目的Demo.这样做的目的 ...
- CDN学习笔记二(技术详解)
一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精华放上网.公诸同 ...
- CDN技术详解及实现原理
CDN技术详解 一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精 ...
- P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解
1.内容概述 P2P即点对点通信,或称为对等联网,与传统的服务器客户端模式(如下图"P2P结构模型"所示)有着明显的区别,在即时通讯方案中应用广泛(比如IM应用中的实时音视频通信. ...
- 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践
本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...
随机推荐
- benchmark 库
性能测试的库 https://github.com/bestiejs/benchmark.js
- shiro使用教程
一.shiro是什么 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.不仅可以在Web项目中使用,在普通的项目中也是可以使用的 二.shiro可以做什 ...
- [认证授权] 2.OAuth2(续) & JSON Web Token
0. RFC6749还有哪些可以完善的? 0.1. 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何 ...
- 【Egret】里使用video标签
egret里使用Html5的Video标签 egret里使用Html5的Video标签的demo: 链接:http://pan.baidu.com/s/1nuNyqRR 密码:x58i //----- ...
- .net mvc------下拉列表DropDownList控件------绑定数据
下拉列表 以性别为例 绑定可以了,可以显示了,但有些地方就能传值,有些地方就会出错提示,如有大神请指教.... 错误如下: 具有键"sex"的 ViewData 项属于类型&quo ...
- Java基础学习(三)—面向对象(上)
一.理解面向对象 面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节:这种思想是将数据作为第一位,而方法或者说是 ...
- matlab函数:c2d离散化函数(待完善)
Convert model from continuous to discrete time sysd =c2d(sys,Ts)sysd =c2d(sys,Ts,method)sysd =c2d(sy ...
- day002-HTML知识点总结:浏览器兼容性之指定IE浏览器使用chrome内核渲染页面
今天再浏览大淘宝首页时,突然看到这么一个东东: ,顿时好费解,莫非万恶的IE浏览器认识到自己以往的罪孽,开始兼容chrome了??! 于是本着不懂就百度的神精,开始纵横于各大铁耙,勃哥,终于找到了许许 ...
- shell初步了解
shell的类型 查看用户所用的shell程序,在/etc/passwd 文件中的第七个字段(好像就是最后一个,主要是bash shell) 还有一个默认shell是/bin/sh,它作为默认的系统s ...
- PHP常用的三种设计模式
本文为大家介绍常用的三种php设计模式:单例模式.工厂模式.观察者模式,有需要的朋友可以参考下. 一.首先来看,单例模式 所谓单例模式,就是确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实 ...