博客列表 >PHP trait 及其应用场景、trait 与接口,抽象类之间的区别

PHP trait 及其应用场景、trait 与接口,抽象类之间的区别

司马青衫
司马青衫原创
2020年07月28日 16:27:102233浏览

PHP trait 及其应用场景、trait 与接口,抽象类之间的区别

  • trait可以使多个无关的类共用同一种方法或属性
  • trait无法实例化,在类中使用use关键字引用

应用场景 1:代码复用

  • 两个无关的类使用同一种方法
  1. <?php
  2. trait tSum{
  3. public function sum($a, $b){
  4. return $a + $b;
  5. }
  6. }
  7. class countNum{
  8. use tSum;
  9. }
  10. class totalPrice{
  11. use tSum;
  12. }
  13. echo (new countNum)->sum(10, 20),'<br>';
  14. echo (new totalPrice)->sum(3, 20),'<br>';

应用场景 2:同名方法在 trait 与父类与子类的关系

  • 同名成员在 trait 中优先级高于子类的父类
  • 同名成员在子类中优先级高于 trait
  • 同名成员在子类中优先级高于父类
  1. <?php
  2. trait tRet{
  3. public static function ret(){
  4. return 'trait';
  5. }
  6. }
  7. class cFRet{
  8. use tRet;
  9. public static function ret(){
  10. return '父类';
  11. }
  12. }
  13. class cSRet extends cFRet{
  14. use tRet;
  15. public static function ret(){
  16. return '子类';
  17. }
  18. }
  19. //此时浏览器上输出子类 可以看出 子类优先级要高于父类与`trait`
  20. //当在子类中注释掉成员方法之后 浏览器上输出trait 可以看出 trait的优先级要高于父类
  21. //当在子类中注释掉use trait之后 浏览器上输出子类 可以看出 类优先级要高于父类
  22. echo cSRet::ret(),'<br>';
  • 当子类中注释trait引用时
  • 显示子类 说明子类比父类优先级高
  • 当子类中注释同名方法时
  • 显示trait 说明trait优先级比父类高
  • 当子类中同时有trait与父类的同名方法时
  • 只显示子类 说明子类优先级最高

应用场景 3:实现功能扩展

  • 在 trait 中设计的成员方法可以被类引用
  • 一个类中可以使用多个 trait 以扩展其中的方法
  1. <?php
  2. trait tRet1{
  3. public static function ret1(){
  4. return '你好';
  5. }
  6. }
  7. trait tRet2{
  8. public static function ret2(){
  9. return 'php';
  10. }
  11. }
  12. trait tRet{ //组合两个trait
  13. use tRet1, tRet2;
  14. }
  15. class cRet{
  16. use tRet; //use tRet1, tRet2;
  17. }
  18. echo cRet::ret1().':'.cRet::ret2();

应用场景 4:trait 中同名成员方法的处理

  • 使用关键字as给其中一个同名方法起个别名
  • 使用关键字insteadOf来明确指定使用冲突方法中的哪一个
  1. <?php
  2. trait hello{
  3. public function hw(){
  4. return 'hello';
  5. }
  6. }
  7. trait world{
  8. public function hw(){
  9. return 'world';
  10. }
  11. }
  12. class hello_wrold{
  13. use hello, world{
  14. hello::hw as hello;
  15. world::hw insteadOf hello;
  16. }
  17. }
  18. echo (new hello_wrold)->hw(),'<br>';
  19. //使用别名访问
  20. echo (new hello_wrold)->hello();
  • 当未使用asinsteadOf时产生冲突
  • 冲突处理之后

    应用场景 5:trait 与接口

  • 使用 trait 实现接口中的方法

  1. <?php
  2. //声明一个接口定义helloWorld方法
  3. interface iHelloWorld{
  4. public function helloWorld();
  5. }
  6. //声明一个triat 实现helloWorld方法
  7. trait tHelloWorld{
  8. public function helloWorld(){
  9. return 'Hello World';
  10. }
  11. }
  12. //声明一个工作类 实现接口 使用trait
  13. class cHelloWorld implements iHelloWorld{
  14. use tHelloWorld;
  15. }
  16. echo (new cHelloWorld)->helloWorld();

trait 与接口,抽象类之间的区别

  • trait是通过代码复用来实现具体功能扩展
  • interface是通过代码声明一些特定功能,没有具体的实现内容
  • 抽象类是对类对象的抽象,不能进行实例化,实际上是某一类的抽象集合
  • 一个实现类可以使用多个trait或者多个interface,但只能继承一个抽象类
  1. <?php
  2. //声明一个接口 特定行为:握手
  3. interface iAction{
  4. public function shakeHands();
  5. }
  6. //声明一个trait 实现握手行为
  7. trait tShakeHands{
  8. public function shakeHands(){
  9. return true;
  10. }
  11. }
  12. //声明一个抽象类 狗类:吠、摇尾巴
  13. abstract class aDogs{
  14. abstract public function bark();
  15. abstract public function wagTail();
  16. }
  17. //实现类 实现一只狗的基本属性行为
  18. class Dog extends aDogs implements iAction{
  19. use tShakeHands;
  20. public function bark(){
  21. return true;
  22. }
  23. public function wagTail(){
  24. return true;
  25. }
  26. }
  27. //输出
  28. $myDog = new Dog();
  29. echo 'my dog '.($myDog->bark()?'can':'cannot').' bark<br>';
  30. echo 'my dog '.($myDog->wagTail()?'can':'cannot').' wagging its tail<br>';
  31. echo 'my dog '.($myDog->shakeHands()?'can':'cannot').' shake hands';

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议