博客列表 >trait的五种常用场景

trait的五种常用场景

王佳祥
王佳祥原创
2020年07月24日 15:39:121119浏览

trait的五种常用场景

一、代码复用

  1. <?php
  2. //1.trait功能1:代码复用
  3. trait tDemo
  4. {
  5. public function show()
  6. {
  7. //get_class_vars — 返回由类的默认属性组成的数组
  8. printf('<pre>%s</pre>',print_r(get_class_vars(__CLASS__),true));
  9. }
  10. }
  11. class User1
  12. {
  13. use tDemo;
  14. protected $name = '胖子';
  15. protected $sex = '男';
  16. }
  17. class User2
  18. {
  19. use tDemo;
  20. protected $name = '胖子';
  21. protected $sex = '男';
  22. }
  23. (new User1)->show();
  24. (new User2)->show();


二、同名成员在trait,子类,父类的优先级

  1. <?php
  2. //trait功能2:在继承上下文中的应用
  3. trait tDemo
  4. {
  5. //public static $name = 'trait中的属性';
  6. public static function hello()
  7. {
  8. //__METHOD__返回类名称与函数名称
  9. //__FUNCTION__返回函数名称
  10. return 'trait中的方法' . __METHOD__;
  11. }
  12. }
  13. //声明一个抽象类 基类/父类/超类
  14. abstract class Dad
  15. {
  16. public static $name = '基类中的属性';
  17. public static function hello()
  18. {
  19. //__METHOD__返回类名称与函数名称
  20. //__FUNCTION__返回函数名称
  21. return '基类中的方法' . __METHOD__;
  22. }
  23. }
  24. //子类/扩展类
  25. class Son extends Dad
  26. {
  27. //引入trait
  28. use tDemo;
  29. public static $name = '扩展类中的属性';
  30. public static function hello()
  31. {
  32. //__METHOD__返回类名称与函数名称
  33. //__FUNCTION__返回函数名称
  34. return '扩展类中的方法' . __METHOD__;
  35. }
  36. }
  37. echo Dad::$name.'<br>';
  38. echo Dad::hello().'<hr>';
  39. //子类同名成员优先级大于父类同名成员
  40. //如果子类,父类,trait中存在同名方法的时候,而trait在子类中调用,此时
  41. //子类>trait>父类
  42. echo Son::$name.'<br>';
  43. echo Son::hello();


三、trait的扩展功能

  1. <?php
  2. //trait功能3: 实现功能扩展
  3. //trait1
  4. trait tDemo1
  5. {
  6. //1.打印所有属性
  7. public function getProps()
  8. {
  9. //__CLASS__返回当前类的名称字符串
  10. //self:返回当前类的引用
  11. printf('<pre>%s</pre>',print_r(get_class_vars(__CLASS__),true));
  12. }
  13. }
  14. //trait2
  15. trait tDemo2
  16. {
  17. //2.打印所有方法
  18. public function getMethods()
  19. {
  20. printf('<pre>%s</pre>',print_r(get_class_methods(__CLASS__),true));
  21. }
  22. }
  23. //trait3,合并trait1,trait2
  24. trait tDemo3
  25. {
  26. use tDemo1,tDemo2;
  27. }
  28. class Work1
  29. {
  30. use tDemo3;
  31. public $name = '西瓜';
  32. public $price = 0.7;
  33. public function getInfo()
  34. {
  35. return $this->name . ':' . $this->price;
  36. }
  37. //扩展这个类的功能
  38. //添加二个方法
  39. //1.打印所有属性
  40. //2.打印所有方法
  41. }
  42. echo (new Work1)->getInfo(),'<hr>';
  43. echo (new Work1)->getProps(),'<hr>';
  44. echo (new Work1)->getMethods(),'<hr>';


四、在trait组合中解决命名冲突的方案

  1. <?php
  2. //trait功能4:在trait组合中命名冲突的解决方案
  3. trait tDemo1
  4. {
  5. public function display()
  6. {
  7. //__TRAIT__:返回trait的名称字符串
  8. return __TRAIT__;
  9. }
  10. }
  11. trait tDemo2
  12. {
  13. public function display()
  14. {
  15. //__TRAIT__:返回trait的名称字符串
  16. return __METHOD__;
  17. }
  18. }
  19. trait tDemo3
  20. {
  21. use tDemo1,tDemo2{
  22. //给tDemo2::display()起个别名:td2
  23. tDemo2::display as td2;
  24. //调用tDemo1::display()替换掉tDemo2::display()
  25. tDemo1::display insteadof tDemo2;
  26. }
  27. }
  28. //工作类尽可能写的代码清晰,简洁
  29. class Work
  30. {
  31. use tDemo3;
  32. }
  33. echo (new Work)->display(),'<hr>';
  34. //别名访问
  35. echo (new Work)->td2();


五、trait和interface的组合

  1. <?php
  2. //trait功能5:trait和interface的组合
  3. //接口
  4. //如果这个接口不存在的话,直接创建这个接口
  5. if (!interface_exists('iDemo')):
  6. interface iDemo
  7. {
  8. public static function index();
  9. }
  10. endif;
  11. //trait
  12. if(!trait_exists('tDemo')):
  13. trait tDemo
  14. {
  15. //将接口中的抽象方法的实现过程放在trait中实现,并在工作中调用
  16. public static function index()
  17. {
  18. return __METHOD__;
  19. }
  20. }
  21. endif;
  22. //实现类
  23. if(!class_exists('Hello')):
  24. class Hello implements iDemo
  25. {
  26. use tDemo;
  27. }
  28. endif;
  29. //客户端调用
  30. echo Hello::index();


六、实战:双色球开奖的背景知识

  1. <?php
  2. //实战:双色球开奖
  3. //抽象类 + 接口 + trait
  4. //奖品
  5. $prizes = ['华为p40手机','山地自行车','机械键盘','音箱','耳机','头盔'];
  6. /* trait iCreateId
  7. {
  8. //生成一个唯一的ID
  9. public static function generateId($min,$max)
  10. {
  11. //返回范围内的随机整数
  12. return mt_rand($min,$max);
  13. }
  14. } */
  15. interface iCreateId
  16. {
  17. public static function generateId($min,$max);
  18. }
  19. trait CreateId
  20. {
  21. public static function generateId($min,$max)
  22. {
  23. //返回范围内的随机整数
  24. return mt_rand($min,$max);
  25. }
  26. }
  27. //开奖类
  28. class DrawPrize implements iCreateId
  29. {
  30. use CreateId;
  31. //发奖品
  32. public static function award($prizes,$id)
  33. {
  34. return $prizes[$id];
  35. }
  36. }
  37. $id = DrawPrize::generateId(0,5);
  38. $prize = DrawPrize::award($prizes,$id);
  39. printf('奖品是:<span style="color:red">%s</span>',$prize);


七、学习总结

1.trait代码复用

2.同名成员在父类,子类,trait中的优先级:子类>trait>父类

3.trait可以扩展功能

4.在trait中可以用别名解决命名冲突的问题

5.trait可以实现接口中的方法并调用

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