谈谈PHP中的trait

  • 前言
  • 目的
  • 应用场景
  • 简单使用
    • 1. 基础代码
    • 2. 调用其中一个trait中的方法
    • 3. 在自己的方法中定义一个和trait中同名的方法
    • 4. 若是我们在类中同时引用两个 trait ,且这两个trait都拥有一个同名方法呢?
      • 4.1. 冲突解决方法一,使用 insteadof 替换
      • 4.2 冲突解决方法二 使用优先级的特性 让类的同名文件将其覆盖掉
    • 5. as取别名后 原来的方法名依旧能使用
    • 6. 进阶知识
      • 6.1 公有的转为私有的
      • 6.2 私有的变为公有的

前言

PHP因为其单继承的特性,无法满足继承多个文件的情况下,在php 5.4版本出现了trait 。use 了某个trait 使用trait中的方法就像是调用自己的方法一样简便。在 trait 中定义基础的方法,方便其他类直接调用。
声明一个 trait 需要使用关键字 trait 调用它需要使用 use,且它无法被实例化。

目的

它存在的目的是为了减少代码的重复性,提高代码的复用性。

应用场景

当有些基础方法使用率比较高,或者是一种规则的定义需要我们统一计算,但他们不是每个类都需要用到时,我们可以考虑将它放入 trait 中。
假如一个类继承了基础类,这个类代码的大小其实是自己的代码大小加上基础类代码量的大小,所有基础类里面我们尽量定义那种每个类中都会用到的方法,并尽量保持基础类文件简洁。
它不仅仅是可复用代码段的集合,它应该是一组描述了某个特性的的属性与方法的集合。它的优点在于随意组合,耦合性低,可读性高

简单使用

1. 基础代码

trait dog{public function eat(){echo '狗吃狗粮</br>';}
}trait cat{public function eat(){echo '猫吃猫粮</br>';}
}class animal{public function eat(){echo '请问动物吃什么</br>';}
}class whatEat extends animal {public function questios(){echo '发起提问</br>';}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();

返回结果

此处只继承了基础类 animal 所以调用eat返回的是 ‘请问动物吃什么’

2. 调用其中一个trait中的方法

class whatEat extends animal {use cat;public function questios(){echo '发起提问</br>';}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();

得到结果:

结论:我们很明显看出来 基础类animal中的eat直接被 cat中的eat覆盖掉了

3. 在自己的方法中定义一个和trait中同名的方法

class whatEat extends animal {use cat;public function questios(){echo '发起提问</br>';}public function eat(){echo '各个动物吃的东西都不同';}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();

得到结果:

结论:从上面我们知道 基础类animal 和whatEat自身,trait cat都拥有一个同名的方法 但是通过 【3】 我们知道了优先级最高的是类本身的方法。通过【2】我们知道了 基础类和trait 拥有同名方法,优先级最高的是trait内的方法。
所有 优先级是 类本身内的方法 > trait中的方法 > 基础类的方法

4. 若是我们在类中同时引用两个 trait ,且这两个trait都拥有一个同名方法呢?

class whatEat extends animal {use cat;use dog;public function questios(){echo '发起提问</br>';}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();

返回结果:

结论:直接报 500 。所有同时引进的 trait 中有同名方法会直接导致类报错。因为不同trait中存在同名方法会存在冲突。
那我们如何处理这种错误呢。解决方法有两个

4.1. 冲突解决方法一,使用 insteadof 替换

class whatEat extends animal {use cat,dog{dog::eat insteadof cat;cat::eat as cateat;}public function questios(){echo '发起提问</br>';}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();
$whatEat->cateat();

返回结果:

结论:cat 中的方法直接被 dog 中的替换掉了。调用类中的 eat 直接返回的是 dog 中的 eat ,而 cat 中的 eat 被重新命名为 cateat 使用

4.2 冲突解决方法二 使用优先级的特性 让类的同名文件将其覆盖掉

class whatEat extends animal {use cat,dog;public function questios(){echo '发起提问</br>';}public function eat(){cat::eat();}public function eat2Dog(){dog::eat();}
}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();
$whatEat->eat2Dog();

返回结果:

结论:将trait中的方法通过 优先级别将其覆盖掉。在定义一个别名方法将被覆盖掉了的方法重新实现出来。

5. as取别名后 原来的方法名依旧能使用

class whatEat extends animal {use cat{cat::eat  as cateat;}public function questios(){echo '发起提问</br>';}}$whatEat = new whatEat();
$whatEat->questios();
$whatEat->eat();
$whatEat->cateat();

返回结果:

结论:不论是使用 eat 这个原本的名字 还是使用在类中重命名之后的 cateat 都得到了返回结果 ‘猫吃猫粮’

6. 进阶知识

as除了可以用来取别名之外 还可以给方法定义权限

6.1 公有的转为私有的

class whatEat extends animal {use cat{cat::eat  as private cateat;}public function questios(){echo '发起提问</br>';}}$whatEat = new whatEat();
$whatEat->questios();
echo 'eat 返回的结果:';
$whatEat->eat();
echo '</br>';echo 'private cateat返回的结果:';
$whatEat->cateat();
echo '</br>';

返回结果:

结论:返回未报错,方法 eat 被正常调用 但是被定义为 private 的 cateat 并没有返回结果。同样测试protected 也没有得到结果 只有定义为public 时候才返回出结果。

6.2 私有的变为公有的

trait cat{public function eat(){echo '猫吃猫粮</br>';}protected function eat2(){echo '猫也吃小鱼干</br>';}
}class animal{public function eat(){echo '请问动物吃什么</br>';}}class whatEat extends animal {use cat{cat::eat2 as public eat22;}public function questios(){echo '发起提问</br>';}
}
$whatEat = new whatEat();
$whatEat->questios();
echo 'eat2 返回的结果:';

返回结果

在看 取别名为 eat22 返回的结果

$whatEat = new whatEat();
$whatEat->questios();
echo 'eat22 返回的结果:';
$whatEat->eat22();

结论: 原本 trait 文件中权限为 protected 的方法 在class里面被重新定义了 权限和命名后,变为了公有方法,可以直接在外部调用。

谈谈PHP中的trait相关推荐

  1. PHP中的Trait方法

    <?php /** 自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait.* Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.* Trait 为了减 ...

  2. html js脚本限制 正则,简单谈谈JS中的正则表达式

    1.正则表达式包括两部分 ①定义正则表达式的规则: ②正则表达式的模式(i/g/m): 2.声明正则表达式 ① 字面量声明: var reg = /表达式规则/表达式模式: eg:var reg = ...

  3. Linux存储保护,谈谈Linux中的存储保护

    谈谈Linux中的存储保护 以下讨论的内容是以i386平台为基础的 Linux将4G的地址划分为用户空间和内核空间两部分.在Linux内核的低版本中(2.0.X),通常0-3G为用户空间,3G-4G为 ...

  4. 谈谈JAVA中的安全发布

    谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...

  5. Spark精华问答 | 谈谈spark中的宽窄依赖

    总的来说,Spark采用更先进的架构,使得灵活性.易用性.性能等方面都比Hadoop更有优势,有取代Hadoop的趋势,但其稳定性有待进一步提高.我总结,具体表现在如下几个方面. 1 Q:Spark ...

  6. 谈谈C#中的三个关键词new , virtual , override

    谈谈C#中的三个关键词new , virtual , override C#支持单继承,说到继承就不得不说new,virtual和override这三个关键词,灵活正确的使用这三个关键词,可以使程序结 ...

  7. 谈谈java中成员变量与成员方法继承的问题

    谈谈java中成员变量与成员方法继承的问题 关于成员变量和成员方法的的继承问题,我也可以做一个小测试,来看看结果. 首先我们先创建一个父类: 其次再创建一个子类,子类中要比父类中少一个成员方法: 这样 ...

  8. kotlin 扩展函数_在 Kotlin 中“实现”trait/类型类

    本文原发于我的个人博客:https://hltj.me/kotlin/2020/01/11/kotlin-trait-typeclass.html.本副本只用于知乎,禁止第三方转载. trait 与类 ...

  9. 也谈谈Javascript中的几个怪异特性(上)

    2019独角兽企业重金招聘Python工程师标准>>> Andy Croxall在Ten Oddities And Secrets About JavaScript罗列了他认为的10 ...

最新文章

  1. 神经网络“天生”就会驾驶虚拟赛车
  2. plsql 循环存储过程返回数据集合_Java基础(十五)——Collection集合、泛型 - 寒江雨
  3. HarmonyOS之AI能力·分词
  4. javascript 面向对象(转)
  5. jquery mobile资源
  6. [渝粤教育] 西南科技大学 经济数学1 在线考试复习资料
  7. [导入]在C++ Builder3下实现程序自动运行的方法
  8. linux驱动之ioctl
  9. MySQL快速生成连续整数
  10. 二极管的结构、特性、参数、稳压管的特性和参数
  11. SQL Server 2005中的CLR(2)
  12. 职业程序员不必那么职业
  13. HadoopMR-Spark-HBase-Hive
  14. mysql innodb数据库引擎_mysql的innodb数据库引擎详解
  15. 干货|手把手教你写单片机的结构体
  16. 玩转Light Blue之添加设备信息
  17. 【高并发解决方案】高并发解决方案汇总
  18. 电感式传感器的原理大白话
  19. android中抽屉控件,Android自定义控件:类QQ抽屉效果
  20. 读书百客:《临江仙引·画舸》赏析

热门文章

  1. SAP中的凭证冲销(红冲、蓝冲)
  2. vue多个关键字高亮
  3. mysql中约束性别_MySQL常见约束
  4. 牛批了第一次见到这么清晰的微服务概述,助你轻松入门到进阶
  5. 【读论文】A Deep Neural Network for Unsupervised Anomaly Detection and Diagnosis in Multivariate Time...
  6. OPENCV之人眼检测
  7. 日期及时间处理包 Carbon 的简单使用
  8. 中国企业如何玩转海外媒体推广?
  9. python计算速度和电脑有关系吗_Python中对数计算的基础会影响速度吗?
  10. ADAS推高毫米波雷达需求,上游企业如何跟进?