PHP Trait代码复用类与多继承实现方法详解


Posted in PHP onJune 17, 2019

本文实例讲述了PHP Trait代码复用类与多继承实现方法。分享给大家供大家参考,具体如下:

前言

众所周知,一直以来PHP和很多语言一样是单继承的语言,但是常常在编码过程中,我们需要在当前类中使用两个或两个以上的其他类的方法,这种情况下继承就不能实现,而往往采用new方式实例化很多要用到的类,这样就会很影响代码的结构和开发规范。于是Trait类诞生了,它是一种代码复用的语法,能够实现一个类中引用多个其他类的方法。

一、概念

PHP官方手册对Trait的描述是:
Trait是为类似PHP的单继承语言而准备的一种代码复用机制。Trait为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用method。Trait和Class组合的语义定义了一种减少复杂性的方式,避免传统多继承和Mixin类相关典型问题。
Trait和Class相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过trait自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个Class之间不需要继承。

二、Trait类的使用

简单地讲,Trait就是一种不同于继承的语法,定义一个trait类,在其他类中使用它则是采用use关键字,有点类似于命名空间的用法,但是含义不同。use关键字在一个类中引入Trait类后,相当于require或include了一段代码进来,不同之处在于use的Trait类与当前类是可以看做同一个类的,即当前类可以用$this关键字调用Trait类的方法。

以下是原理解释:

PHP Trait代码复用类与多继承实现方法详解

可以看出当前类可以简单地use两个Trait类,并调用其中的方法,而不仅限于继承,只能使用一个父类的方法。

三、Trait类的访问控制

我们知道,继承的方式,如果基类是private修饰控制的,则子类是无法调用的。但是Trait不一样,因为它类似于Require到当前类中了,所以不管是public、protected或private都是可以直接使用的。示例如下:

PHP Trait代码复用类与多继承实现方法详解

四、Trait类的优先级控制

Trait类与当前使用类、继承的基类之间的调用优先级顺序如下:
当前使用类>Trait类>继承的基类

当存在同名方法时,会根据优先级覆盖掉同名的类。具体示例如下:

1、Trait类覆盖基类

PHP Trait代码复用类与多继承实现方法详解

2、当前类覆盖Trait类

PHP Trait代码复用类与多继承实现方法详解

五、多个Trait类的冲突控制

在PHP中,如果当前类use了两个Trait类,同时两个trait类都存在一个同名的方法,此时如果没有明确解决冲突将会产生一个致命错误。
对于这种情况,PHP官方给出了两个解决方案:
1、insteadof关键字:通过该关键字指定方法名冲突时该使用哪个Trait类的方法,即:
如果C类use了A、B两个Trait类,且A、B两个类都存在a、b方法,则在C类use A、B类时使用insteadof声明冲突的解决方法即可:

use A, B {
  B::a insteadof A; //a方法冲突时使用B类的a方法而不使用A类的a方法
  A::b insteadof B; //b方法冲突时使用A类的b方法而不使用B类的b方法
}

2、as关键字:通过as关键字将同名方法指定为一个别名,且仅作用于当前类中。示例如下:

use A, B {
  B::a as c; //声明B类的a方法为c,作用于该类
  A::b as d; //声明A类的b方法为d,作用于该类
}

六、与继承、直接实例化的区别

对于当前一个类需要用到另一个或多个类的方法的情况,我们一般会想到的方式有继承、直接实例化另外一个或多个类等等的方法,下面来对比一下这些方法和Trait类的区别:
1、继承方式:对于继承,可以完美地复用另一个类的一些方法,但是对于需要复用多个类的方法时,PHP是不支持多继承的,而且只能访问public和protected方法;
2、与直接实例化的区别:我们也可以在当前类中直接实例化要用到的A类与B类,但是这种方法在控制访问范围反面,只允许访问A、B类中public的方法;
3、使用Trait类则完全将A、B两个类的方法导入到当前类中,可以视为当前类的一部分,唯一区别是可以存在于当前类同名的方法,此时由优先级顺序来控制。

补充:PHP多继承示例

class Base{
  public function sayHello(){
    echo "hello ";
  }
}
trait SayWorld{
  public function sayHello(){
    parent::sayHello();
    echo "world".PHP_EOL;
  }
}
trait SayWorld2{
  public function sayHello2(){
    echo "PHP".PHP_EOL;
  }
}
class MyHelloWorld extends Base{
  use SayWorld,SayWorld2;
}
$s = new MyHelloWorld();
$s->sayHello();
$s->sayHello2();

输出结果:

hello  world
PHP

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php 随机生成10位字符代码
Mar 26 PHP
基于PHP异步执行的常用方式详解
Jun 03 PHP
PHP中nowdoc和heredoc使用需要注意的一点
Mar 21 PHP
通过curl模拟post和get方式提交的表单类
Apr 23 PHP
教你如何用php实现LOL数据远程获取
Jun 10 PHP
ThinkPHP之foreach标签使用概述
Jun 30 PHP
Laravel 4 初级教程之视图、命名空间、路由
Oct 30 PHP
phpMyAdmin安装并配置允许空密码登录
Jul 04 PHP
Yii列表定义与使用分页方法小结(3种方法)
Jul 15 PHP
thinkPHP中验证码的简单实现方法
Dec 05 PHP
PHP自定义函数判断是否为Get、Post及Ajax提交的方法
Jul 27 PHP
PHP集成环境XAMPP的安装与配置
Nov 13 PHP
php设计模式之装饰模式应用案例详解
Jun 17 #PHP
php设计模式之策略模式应用案例详解
Jun 17 #PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
Jun 17 #PHP
PHP 并发场景的几种解决方案
Jun 14 #PHP
PHP 实现文件压缩解压操作的方法
Jun 14 #PHP
php反射学习之依赖注入示例
Jun 14 #PHP
php反射学习之不用new方法实例化类操作示例
Jun 14 #PHP
You might like
php 无限级缓存的类的扩展
2009/03/16 PHP
深入解析PHP垃圾回收机制对内存泄露的处理
2013/06/14 PHP
PHP5中GD库生成图形验证码(有汉字)
2013/07/28 PHP
yii2项目实战之restful api授权验证详解
2017/05/20 PHP
PHP 实现 WebSocket 协议原理与应用详解
2020/04/22 PHP
一步一步教你写一个jQuery的插件教程(Plugin)
2009/09/03 Javascript
分享一个用Mootools写的鼠标滑过进度条改变进度值的实现代码
2011/12/12 Javascript
js中定义一个变量并判断其是否为空的方法
2014/05/13 Javascript
学习JavaScript编程语言的8张思维导图分享
2015/03/27 Javascript
jquery实现的代替传统checkbox样式插件
2015/06/19 Javascript
静态页面html中跳转传值的JS处理技巧
2016/06/22 Javascript
jQuery和hwSlider实现内容响应式可触控滑动切换效果附源码下载(二)
2016/06/22 Javascript
js修改onclick动作的四种方法(推荐)
2016/08/18 Javascript
前端开发之CSS原理详解
2017/03/11 Javascript
DataTables添加额外的查询参数和删除columns等无用参数实例
2017/07/04 Javascript
Vue中使用Sortable的示例代码
2018/04/07 Javascript
详解Angular5路由传值方式及其相关问题
2018/04/28 Javascript
一个手写的vue放大镜效果
2019/08/09 Javascript
javascript实现动态时钟的启动和停止
2020/07/29 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
[10:34]DOTA2上海特级锦标赛全纪录
2016/03/25 DOTA
[01:00:44]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第三局
2016/03/04 DOTA
[56:20]LGD vs VP Supermajor 败者组决赛 BO3 第三场 6.10
2018/07/04 DOTA
python学习必备知识汇总
2017/09/08 Python
python3实现点餐系统
2019/01/24 Python
python中时间、日期、时间戳的转换的实现方法
2019/07/06 Python
利用Python脚本批量生成SQL语句
2020/03/04 Python
Python实现Appium端口检测与释放的实现
2020/12/31 Python
让IE支持CSS3的不完全兼容方案
2014/09/19 HTML / CSS
波兰购物网站:MALL.PL
2019/05/01 全球购物
安德玛菲律宾官网:Under Armour菲律宾
2020/07/28 全球购物
实习老师离校感言
2014/02/03 职场文书
企业精细化管理实施方案
2014/03/23 职场文书
项目建议书
2015/02/04 职场文书
爱国主题班会教案
2015/08/14 职场文书
学校教代会开幕词
2016/03/04 职场文书