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

为什么使用Trait

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

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

如何创建Trait

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

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

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

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

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

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

如何使用Trait

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

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

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

现代 PHP 新特性系列(三) —— Trait 概览的更多相关文章

  1. Java8新特性系列-默认方法

    Java8 Interface Default and Static Methods 原文连接:Java8新特性系列-默认方法 – 微爱博客 在 Java 8 之前,接口只能有公共抽象方法. 如果不强 ...

  2. Java8新特性系列-Lambda

    转载自:Java8新特性系列-Lambda – 微爱博客 Lambda Expressions in Java 8 Lambda 表达式是 Java 8 最流行的特性.它们将函数式编程概念引入 Jav ...

  3. UWP/Win10新特性系列—App Service

    Win10中,新增了一个很实用的新特性叫做App Service,App Service允许App不在前台运行的情况下提供出一个或多个对外服务供其他App使用,这看起来就好像Web开发中的Web Ap ...

  4. Java8新特性(一)概览

    最近看了好几段Java代码和以往的风格很不一样,都有点不太适应了,后来一查原来是Java8的新特性. 为了保持对技术的敏感性(面试...),这里我们一起来学习下Java8的新特性. 如果从技术角度来看 ...

  5. ArcGIS Server 10.1新特性系列---动态图层

    ArcGIS Server 10.1新特性里面有几个新功能是非常棒的,其中有一个就是动态图层.动态图层不是一种新发明的图层,而是说在arcgis server的web应用中可以动态的配置其渲染和内容功 ...

  6. Java8新特性(三)——Optional类、接口方法与新时间日期API

    一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...

  7. UWP/Win10新特性系列—Drag&Drop 拖动打开文件

    在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版 ...

  8. SQL Server 2014 BI新特性(三)Power Query和Power Map功能预览

    Power Query和Power Map是微软前不久在WPC上发布的Power BI中新的针对Excel的功能.借助这两样功能,自助式BI将更方便你发现和处理数据并且丰富数据的可视化功能. Powe ...

  9. 【转】Win10/UWP新特性系列—Web

    Internet Explorer Internet Explorer 在Windows 10 升级为Edge模式,是一种交互性和兼容性都很强的新型浏览器,该浏览器相比以前的版本更新了超过2000个操 ...

随机推荐

  1. Oracle学习笔记_08_字符串连接

    附录:参考资料 1.Oracle中字符串连接的实现方法 2.SQL指令— CONCAT(字符串连接函数)

  2. Webpack 2 视频教程 008 - WDS 端口号等配置相关

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  3. bug运输[辽宁2014年省队互测一]

    奇奇怪怪的题目,不知道他要我们干什么. 我们观察一波局势,发现答案最大不过5.因为如果答案是6或以上的话,我们就至少要2^(5*5)个5*5的方格. 仔细计算一波时间复杂度,再信仰一波,坚信暴力压正解 ...

  4. mayavi安装

    Mayavi是python的一个包,提供方便的可视化方案.目前(20150809)Mayavi还没有py3的支持,以下安装环境在python 2.7.10下进行 安装Mayavi: 1. 通过pip ...

  5. 【精选】Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...

  6. socket对象放在一个datagridview的row的tag里面在拿出来 为什么是已释放

     socket对象放在一个datagridview的row的tag里面在拿出来 为什么是已释放 

  7. angular4.0单个标签不能同时使用ngFor和ngIf

    这个问题估计是ng4严格了语法规范的原因. 介于这篇太短,附上图助助兴致 解决办法: <div *ngFor="表达式"> <ng-container *ngIf ...

  8. Java框架之Hibernate(二)

    本文主要介绍: 1 Criteria 接口 2 用 myeclipse 反向生成 3 hibernate  主键生成策略 4 多对一 5 一对多 6 使用List 集合的一对多 7 多对多 一.Cri ...

  9. JAVA中的设计模式三(策略模式)

    问题: 如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化?   方案: 把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就 ...

  10. PyQt4 开发入门

    参考资料:PyQt4教程