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

 更新时间:2019年06月17日 11:58:05   作者:George-Henry  
这篇文章主要介绍了PHP Trait代码复用类与多继承实现方法,结合实例形式详细分析了Trait代码复用类的原理并结合具体实例形式分析了php基于Trait多继承的相关实现与使用技巧,需要的朋友可以参考下

本文实例讲述了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类的方法。

以下是原理解释:

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

三、Trait类的访问控制

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

四、Trait类的优先级控制

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

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

1、Trait类覆盖基类

2、当前类覆盖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数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总

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

相关文章

  • php自动加载方式集合

    php自动加载方式集合

    这篇文章主要针对php自动加载方式进行大集合,一种是常规加载方式,另一种是__autoload()自动加载,想知道第三种方式请阅读下文
    2016-04-04
  • ThinkPHP 模板引擎使用详解

    ThinkPHP 模板引擎使用详解

    thinkphp系统支持原生的PHP模板,而且本身内置了一个基于XML的高效的编译型模板引擎,系统默认使用的模板引擎是内置模板引擎,关于这个模板引擎的标签详细使用可以参考模版引擎部分。
    2017-05-05
  • 并发下常见的加锁及锁的PHP具体实现代码

    并发下常见的加锁及锁的PHP具体实现代码

    用到了Eaccelerator的内存锁 和 文件锁,原理如下判断系统中是否安了EAccelerator 如果有则使用内存锁,如果不存在,则进行文件锁
    2010-10-10
  • RSA实现JS前端加密与PHP后端解密功能示例

    RSA实现JS前端加密与PHP后端解密功能示例

    这篇文章主要介绍了RSA实现JS前端加密与PHP后端解密功能,结合实例形式分析了rsa前端js加密与后端php解密相关操作技巧,需要的朋友可以参考下
    2019-08-08
  • php设计模式 Factory(工厂模式)

    php设计模式 Factory(工厂模式)

    定义一个用于创建对象的接口,让子类决定将哪一个类实例化,使用一个类的实例化延迟到其子类
    2011-06-06
  • php校验表单检测字段是否为空的方法

    php校验表单检测字段是否为空的方法

    这篇文章主要介绍了php校验表单检测字段是否为空的方法,涉及php验证表单的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-03-03
  • php学习之function的用法

    php学习之function的用法

    用户自定义函数也称自定义函数,它们不是PHP提供的,是由程序员创建的.由于自己创建了这样的函数,所以就可以完全控制这些函数.因此可以让一个函数完全按照自己希望的方式运行
    2012-07-07
  • PHP 弱引用的相关总结

    PHP 弱引用的相关总结

    这篇文章主要介绍了PHP 弱引用的相关总结,帮助大家更好的理解和学习使用PHP,感兴趣的朋友可以了解下
    2021-05-05
  • php简单图像创建入门实例

    php简单图像创建入门实例

    这篇文章主要介绍了php简单图像创建方法,实例分析了php图像创建的基本技巧,需要的朋友可以参考下
    2015-06-06
  • PHP中iconv函数知识汇总

    PHP中iconv函数知识汇总

    iconv函数库能够完成各种字符集间的转换,是php编程中不可缺少的基础函数库。本文内容是参考了网上的其他资源,然后结合自己的实践,有需要的小伙伴可以参考下。
    2015-07-07

最新评论