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生成月历代码
Jun 14 PHP
PHP iconv 解决utf-8和gb2312编码转换问题
Apr 12 PHP
PHP面向对象学习笔记之二 生成对象的设计模式
Oct 06 PHP
通过dbi使用perl连接mysql数据库的方法
Apr 16 PHP
PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍
Jan 20 PHP
PHP中数据类型转换的三种方式
Apr 02 PHP
详解Yii实现分页的两种方法
Jan 14 PHP
PHP基于ORM方式操作MySQL数据库实例
Jun 21 PHP
PHP魔术方法之__call与__callStatic使用方法
Jul 23 PHP
PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】
Apr 27 PHP
PHP实现微信小程序人脸识别刷脸登录功能
May 24 PHP
php的扩展写法总结
May 14 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
使用无限生命期Session的方法
2006/10/09 PHP
php jq jquery getJSON跨域提交数据完整版
2013/09/13 PHP
php用正则表达式匹配URL的简单方法
2013/11/12 PHP
php表单处理操作
2017/11/16 PHP
PHP排序算法之简单选择排序(Simple Selection Sort)实例分析
2018/04/20 PHP
用Juery网页选项卡实现代码
2011/06/13 Javascript
in.js 一个轻量级的JavaScript颗粒化模块加载和依赖关系管理解决方案
2011/07/26 Javascript
实现动画效果核心方式的js代码
2013/09/27 Javascript
如何将网页表格内容导入excel
2014/02/18 Javascript
node.js微信公众平台开发教程
2016/03/04 Javascript
浅析Javascript的自动分号插入(ASI)机制
2016/09/29 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
2016/11/22 Javascript
自定义require函数让浏览器按需加载Js文件
2016/11/24 Javascript
Js 利用正则表达式和replace函数获取string中所有被匹配到的文本(推荐)
2018/10/28 Javascript
NodeJs 实现简单WebSocket即时通讯的示例代码
2019/08/05 NodeJs
Vue项目配置跨域访问和代理proxy设置方式
2020/09/08 Javascript
关于better-scroll插件的无法滑动bug(2021通过插件解决)
2021/03/01 Javascript
在python下读取并展示raw格式的图片实例
2019/01/24 Python
使用WingPro 7 设置Python路径的方法
2019/07/24 Python
pytorch numpy list类型之间的相互转换实例
2019/08/18 Python
基于Python+Appium实现京东双十一自动领金币功能
2019/10/31 Python
图解python全局变量与局部变量相关知识
2019/11/02 Python
利用Python实现某OA系统的自动定位功能
2020/05/27 Python
Python3爬虫mitmproxy的安装步骤
2020/07/29 Python
python mock测试的示例
2020/10/19 Python
PyCharm Community安装与配置的详细教程
2020/11/24 Python
System.Array.CopyTo()和System.Array.Clone()有什么区别
2016/06/20 面试题
检察官就职演讲稿
2014/01/13 职场文书
公司口号大全
2014/06/11 职场文书
公司离职证明样本
2014/09/13 职场文书
大学军训通讯稿(2016最新版)
2015/12/21 职场文书
2016年世界人口日宣传活动总结
2016/04/05 职场文书
导游词之大雁塔景区
2019/09/17 职场文书
导游词之山西-五老峰
2019/10/07 职场文书
Java中多线程下载图片并压缩能提高效率吗
2021/07/01 Java/Android
使用CSS实现一个搜索引擎的原理解析
2021/09/25 HTML / CSS