现代 PHP 新特性系列(三) —— Trait 概览

现代 PHP 新特性系列(三) —— Trait 概览

Trait是PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么;提供模块化实现。Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制。

为什么使用Trait

PHP语言使用一种典型的单继承模型,在这种模型中,我们先编写一个通用的根类,实现基本的功能,然后扩展这个根类,创建更具体的子类,直接从父类继承实现。这叫做继承层次结构,很多编程语言都使用这个模式。大多数时候这种典型的继承模型能够良好运作,但是如果想让两个无关的PHP类具有类似的行为,应该怎么做呢?

Trait就是为了解决这种问题而诞生的。Trait能够把模块化的实现方式注入多个无关的类中,从而提高代码复用,符合DRY(Don’t Repeat Yourself)原则。比如Laravel底层用户认证相关逻辑以及软删除实现等地方都使用了Trait来实现。以Laravel自带的AuthController为例,其中的登录、注册以及登录失败尝试次数都是通过Trait实现:

trait-userauthencation

如何创建Trait

创建Trait很简单,跟创建类有点类似,只不过使用的关键字是trait而不是class,以上述ThrottlesLogin为例:

trait-throttleslogin

我们通过trait声明定义的是一个Trait,然后我们可以在这个Trait中像类一样定义要使用的属性和方法。

此外Trait支持嵌套和组合,即通过一个或多个Trait(多个用,分隔)组合成一个Trait,比如AuthenticatesAndRegistersUsers即是如此:

trait-authcontroller

使用多个Trait可能会引起命名冲突问题,上面的代码给出了解决方案:使用insteadof关键字,如果AuthenticatesUsers和RegistersUsers中都定义了redirectPath和getGuard方法,那么将从AuthenticatesUsers中获取对应方法而不是RegistersUsers。另外还可以使用as关键字为方法起个别名,这样也可以避免命名冲突。

此外,这里可能没有完整列出,Trait中还支持定义抽象方法和静态方法,其中抽象方法必须在使用它的类中实现。

这里还需要声明的一点是调用方法的优先级:调用类>Trait>父类(如果有的话),方法可以覆盖,但属性不行,如果Trait中定义了一个属性,如果调用类中也定义这个属性则会报错。

如何使用Trait

Trait的使用方法也很简单,上面已经显示的很清楚明了,即使用use关键字。

可能你已经注意到,命名空间和Trait使用的都是use关键字,不同之处在于导入位置,命名空间在类的定义体外导入,而Trait在类的定义体内导入。

注:PHP解释器在编译时会把Trait复制到类的定义体中,但是不会处理这个操作引入的不兼容问题,如果Trait假定类中有特定的属性或方法,需要先确保类中确实有相应的属性或方法。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/113820.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑本篇文章中,我们将一起学习OpenCV中边缘检测的各种算子和滤波器——Canny算子,Sobel算子,Laplace算子以及Scharr滤波器。文章中包含了五个浅墨为大家准备的详细注释的博文配套源代码。在介绍四块知识点的时候分别一个,以及最后的综合示例中的一个。依然是是放出一些程序运行截图吧:效果图看完,我们来唠唠嗑。首先,需要说明的是,浅墨这篇文章最后的示例代码是采用两周前刚刚发布的2.4.9来书写的。里面的lib都已经改成了2.4.9版本的。如果大家需要运行的话,要么配置好2.4.9.要么把浅墨

    2022年5月30日
  • SIGPIPE信号问题

    SIGPIPE信号问题
    socket编程问题
    SIGPIPE信号问题=========================
    当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。
       根据信号的默认处理规则SIGPIPE信号的默认执行动作是terminate(终止、退出),所以client会退出。若不想客户端退出可以把SIGP

    2022年5月29日
  • python %s%d(古代汉语中字的用法)

    %s格式化字符串print(‘str1%s’%’str2’)>>str1str2#意思是%作为一个替代,将后面的‘str2’字符串加到str1后面案例示范具体用法string="hello"#%s打印时结果是helloprint"string=%s"%string#output:string=hello#…

    2022年4月10日
  • tomcat 设置允许跨域访问「建议收藏」

    tomcat 设置允许跨域访问「建议收藏」既然想到使用tomcat进行跨域的设置,而不使用在项目中设置header来解决,说明你也是tomcat下的资源需要做跨域处理吧?这也是一个统一的允许跨域设置,tomcat下的所有请求都将放开,请注意。具体步骤:1.首先找到你的tomcat所在路径,并在conf文件夹下找到web.xml2.打开该文件,在以下位置加上这段:<filter><…

    2022年9月30日
  • windows 10 安装composer问题[通俗易懂]

    windows 10 安装composer问题[通俗易懂]选择手动安装composerhttps://getcomposer.org/download/我选的1.10.0版本

    2022年8月18日
  • Tomcat下载安装并部署到IDEA的教程(附带idea两种热部署设置方法)

    这篇文章主要介绍了Tomcat下载安装并部署到IDEA的教程(附带idea两种热部署设置方法),本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    2022年3月13日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号