Trait是PHP 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关键字,如果AuthenticatesUsers和RegistersUsers中都定义了redirectPath和getGuard方法,那么将从AuthenticatesUsers中获取对应方法而不是RegistersUsers。另外还可以使用as关键字为方法起个别名,这样也可以避免命名冲突。

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

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

如何使用Trait

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

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

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

Trait 概览的更多相关文章

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

    Trait是PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait ...

  2. PHP新特性Trait

    Trait是PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait ...

  3. Activity之概览屏幕(Overview Screen)

    概览屏幕 概览屏幕(也称为最新动态屏幕.最近任务列表或最近使用的应用)是一个系统级别 UI,其中列出了最近访问过的 Activity 和任务. 用户可以浏览该列表并选择要恢复的任务,也可以通过滑动清除 ...

  4. Atitit 软件工程概览attilax总结

    Atitit 软件工程概览attilax总结 1.1. .2 软件工程的发展 进一步地,结合人类发展史和计算机世界演化史来考察软件工程的发展史. 表2 软件工程过程模型 表2将软件工程的主要过程模型做 ...

  5. Scala快速概览

    IDEA工具安装及scala基本操作 目录 一. 1. 2. 3. 4. 二. 1. 2. 3. 三. 1. 2. 3. 4. 5. 6. 7. 四. 1. (1) (2) (3) (4) (5) ( ...

  6. php中trait(性状)与generator(生成器)

    PHP中trait(性状)与generator(生成器) 一.trait (性状) 最近在看Josh Lockhat的<Modern PHP>,这本书很薄.但是其中给出了一个很重要的学习方 ...

  7. 【转】PHP的Trait 特性

    Trait是在PHP5.4中加入的,它既不是接口也不是类.主要是为了解决单继承语言的限制.是PHP多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情 ...

  8. Beginning Scala study note(7) Trait

    A trait provides code reusability in Scala by encapsulating method and state and then offing possibi ...

  9. iOS开发系列—Objective-C之基础概览

    概览 前面我们已经用了几章内容进行C语言介绍,当然要通过几篇文章完整的介绍C语言的知识是不太现实的,例如C语言的文件操作.内存申请等我们都没有重点介绍,当然核心知识点基本都已经提到了,后面有时间我们会 ...

随机推荐

  1. Oracle序列和伪表

    创建序列 create sequence sq_teacher_tnostart with 10 从哪一个数字开始increment by 1 每次增长的数字maxvalue 999999999999 ...

  2. test20181024 qu

    题意 分析 极似UVa11995 I Can Guess the Data Structure! 模拟即可,时间复杂度(--)\(O(n \log n)\) 旁边的L君:这题有两个坑点,我被卡了一次. ...

  3. chrom调试javascript

    上面的文章已经大致介绍了一下console对象具体有哪些方面以及基本的应用,下面简单介绍一下如何利用好chrome控制台这个神器好好调试javascript代码(这个才是我们真正能用到实处的地方) 1 ...

  4. oracle计算两个日期的时间差时分秒

    Oracle函数可以实现诸多的功能,下面就介绍使用oracle函数计算时间差的实现方法. 两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒 ...

  5. 黄聪:自定义WordPress前台、后台顶部菜单栏管理工具条的技巧

    使用WordPress开发网站项目,很多时候都需要对进行后台定制,今天倡萌主要分享下自定义顶部管理工具条的使用技巧. 注:如无特殊说明,请将下面的代码添加到主题的 functions.php  或者插 ...

  6. php7新特性一览

    1.太空船操作符 用于比较2个表达式,例如当\(a小于,等于或大于\)b时,分别返回-1,0,1 php echo 1 <=> 1; //0 echo PHP_EOL; echo 1 &l ...

  7. 学习blus老师js(3)--定时器的使用

    1.无缝滚动——基础 物体运动基础 让Div移动起来 offsetLeft的作用 用定时器让物体连续移动   offsetLeft: 获取物体的左边距:最大的优点在于可以综合考虑所有影响这个物体位置的 ...

  8. [nginx]lua操作redis

    local redis = require "resty.redis" local red = redis:new() red:set_timeout() -- sec -- or ...

  9. 关于sqoop --split-by 及 -m的理解

    场景: sqoop import --connect jdbc:postgresql://...../..... --username ....  --query "select * fro ...

  10. Quartz实现JAVA定时任务的动态配置

    什么是动态配置定时任务? 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 定时任务实现方式千人千种,不过基础的无外乎 1.JDK 的Timer类 2. ...