博客列表 >trait五种应用场景,它与接口interface,抽象类之间的区别-php-26课7.23

trait五种应用场景,它与接口interface,抽象类之间的区别-php-26课7.23

希望
希望原创
2020年07月24日 19:09:58932浏览

一、trait五种应用场景


1. trait功能1:代码复用

  • 公共show在trait里,包含属性和数组,如何打印两组类里的数组?
    1. <?php
    2. trait tDemo
    3. {
    4. // 方法show
    5. public function show()
    6. {
    7. // 打印所有的属性,打印数组,获取属性get_class_vars(__CLASS__)
    8. printf('<pre>%s</pre>', print_r(get_class_vars(__CLASS__), true));
    9. }
    10. }
    11. class User1
    12. {
    13. use tDemo;
    14. // 属性
    15. protected $name = '小刘';
    16. protected $gender = '男';
    17. }
    18. (new User1)->show();
    19. class User2
    20. {
    21. use tDemo;
    22. // 属性
    23. protected $name = '小芳';
    24. protected $gender = '女';
    25. }
    26. (new User2)->show();

    2. trait功能2:在继承上下文中的应用

  • 子类>trait>父类
    1. <?php
    2. trait tDemo
    3. {
    4. public static function hello()
    5. {
    6. return 'trait中的方法' . __METHOD__;
    7. }
    8. }
    9. // 不常用的声明为抽象类abstract,基类/父类/超类
    10. // __METHOD__魔术常量
    11. abstract class Dad
    12. {
    13. public static function hello()
    14. {
    15. return '基类中的方法' . __METHOD__;
    16. }
    17. }
    18. // 子类,扩展类
    19. class Son extends Dad
    20. {
    21. }
    22. echo Son::hello();

    3. trait功能3:实现功能扩展

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

4. trait功能4:同名处理

  • 方法display同名时,给个别名td2
  1. <?php
  2. trait tDemo1
  3. {
  4. public function display()
  5. {
  6. // 打印trait值和方法名称
  7. return __METHOD__;
  8. }
  9. }
  10. trait tDemo2
  11. {
  12. public function display()
  13. {
  14. // 打印trait值和方法名称
  15. return __METHOD__;
  16. }
  17. }
  18. trait tDemo3
  19. {
  20. use tDemo1, tDemo2 {
  21. // 方法同名时,给个别名td2
  22. tDemo2::display as td2;
  23. // 声明调用tDemo1::display()替换掉tDemo2::display()
  24. tDemo1::display insteadOf tDemo2;
  25. }
  26. }
  27. class Work
  28. {
  29. use tDemo3;
  30. }
  31. echo (new Work)->display();
  32. echo "<hr>";
  33. echo (new Work)->td2();

5. trait功能5:trait和interface接口组合

  1. <?php
  2. interface iDemo
  3. {
  4. public static function index();
  5. }
  6. trait tDemo
  7. {
  8. public static function index()
  9. {
  10. return __METHOD__;
  11. }
  12. }
  13. class Hello implements iDemo
  14. {
  15. use tDemo;
  16. }
  17. echo Hello::index();
  • 以上为trait5种应用场景,客户端打印如下图:

二、trait与接口,抽象类之间的区别,用双色球做实例


1. 抽象类+接口interface+trait,创建demo6.php

  • 接口interface中的抽象类方法可以放在trait中,并引入到当前工作类中
  1. <?php
  2. // 双色球开奖奖品
  3. $prizes = ['手机' ,'电脑', '10万', '100万', '汽车'];
  4. interface iCreateId
  5. {
  6. // 声明一个方法
  7. public static function generateId($min, $max);
  8. }
  9. trait createId
  10. {
  11. // 生成一个唯一ID,用一个方法
  12. public static function generateId($min, $max)
  13. {
  14. return mt_rand($min, $max);
  15. }
  16. }
  17. // 开奖类
  18. class DrawPrize implements iCreateId
  19. {
  20. // 把接口中的抽象方法放在trait中,并引入到当前工作类中
  21. use createId;
  22. // 发奖品
  23. public static function award($prizes, $id)
  24. {
  25. return $prizes[$id];
  26. }
  27. }
  28. // 奖品id从0开始,奖品随机
  29. $id = DrawPrize::generateId(0 ,4);
  30. // echo $id;
  31. // 生成奖品
  32. $prize = DrawPrize::award($prizes, $id);
  33. printf('奖品:<span style="color:red">%s</span>', $prize);

2. 把demo6.php引入到demo7.php,双色球开奖实战,随机生成开奖号码与试机号码

  1. <?php
  2. // 双色球开奖实战
  3. // 引入接口iCreateId,trait,createId
  4. require 'demo6.php';
  5. // 抽象类:彩票
  6. abstract class Lottery implements iCreateId
  7. {
  8. use createId;
  9. // 1.生成中奖所需球的编号
  10. protected static function createBalls($min, $max, $num)
  11. {
  12. // 按照规则生成指定步长与数量的编号
  13. $allBalls = range($min, $max, 1);
  14. // 根据球的数量来区别是红球还是篮球
  15. if ($num === 1) return $allBalls[array_rand($allBalls)];
  16. // 取红球,指定哪些可出现,过滤并判断,出现过的值就不要再出现在结果中
  17. // 生成一组,不重复的
  18. $redBallskeys = array_rand($allBalls, $num);
  19. $redBalls = [];
  20. // 遍历由6个键名组成的数组,根据每个键名 从红球数组中随机取出6个,组成一个新数组$redBalls
  21. foreach (array_rand($allBalls, $num) as $key){
  22. $redBalls [] = $allBalls[$key];
  23. }
  24. return $redBalls;
  25. }
  26. // 2.生成一组中奖号码
  27. //6个红球,1个篮球: red[1,33,6],bule[1,16,1]
  28. abstract protected static function doubeColorBall(array $redRule, array $blueRule);
  29. // 3.随机生成一组号
  30. abstract protected static function createRandBalls(array $redRule, array $blueRule, array $range);
  31. }
  32. // 实现类:抽奖类
  33. class DrawLottery extends Lottery
  34. {
  35. // 生成一组中奖号码
  36. public static function doubeColorBall(array $redRule, array $blueRule)
  37. {
  38. // 生成红球 red[1,33,6]
  39. $redBalls = self::createBalls(...$redRule);
  40. sort($redBalls);
  41. // 生成篮球bule[1,16,1]
  42. $blueBalls = self::createBalls(...$blueRule);
  43. // sort($buleBalls);
  44. // 红球与篮球组合,生成一组号码
  45. array_push($redBalls, $blueBalls);
  46. return $redBalls;
  47. }
  48. // 随机生成5组号
  49. public static function createRandBalls(array $redRule, array $blueRule, array $range=[1, 10])
  50. {
  51. $count = self::generateId(...$range);
  52. $randBalls = [];
  53. for ($i = 0; $i< $count; $i++){
  54. $randBalls[]=self::doubeColorBall($redRule, $blueRule);
  55. }
  56. return $randBalls;
  57. }
  58. }
  59. $draw = DrawLottery::doubeColorBall([1,33,6], [1,16,1]);
  60. // 生成5组试机号
  61. $randBalls = DrawLottery::createRandBalls([1,33,6], [1, 16, 1], [1,5]);
  62. ?>
  63. <!doctype html>
  64. <html lang="en">
  65. <head>
  66. <meta charset="UTF-8">
  67. <meta name="viewport"
  68. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  69. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  70. <title>模拟双色球</title>
  71. <style>
  72. .container1 {
  73. display: grid;
  74. grid-template-columns: repeat(7, 40px);
  75. gap: 10px;
  76. margin-top: 10px;
  77. }
  78. .container1 > .ball {
  79. width: 40px;
  80. height: 40px;
  81. color: white;
  82. font-weight: bold;
  83. text-shadow: 1px 1px 1px #555;
  84. border-radius: 50%;
  85. box-shadow: 3px 3px 3px #888;
  86. text-align: center;
  87. line-height: 40px;
  88. }
  89. .container1 > .ball:nth-of-type(-n+6) {
  90. background-color: red;
  91. }
  92. .container1 > .ball:last-of-type {
  93. background-color: deepskyblue;
  94. }
  95. </style>
  96. </head>
  97. <body>
  98. <h2>模拟双色球开奖</h2>
  99. <h3>今日开奖号码: <small style="color: green"><?=date('Y年m月d日', time())?></small></h3>
  100. <div class="container1">
  101. <?php foreach ($draw as $item) : ?>
  102. <span class="ball"><?=$item?></span>
  103. <?php endforeach;?>
  104. </div>
  105. <hr>
  106. <h3>今日试机号:</h3>
  107. <!--将上面显示一组号码的代码再套一个外层循环就可以-->
  108. <?php foreach ($randBalls as $draw): ?>
  109. <div class="container1">
  110. <?php foreach ($draw as $item) : ?>
  111. <span class="ball"><?=$item?></span>
  112. <?php endforeach;?>
  113. </div>
  114. <?php endforeach;?>
  115. </body>
  116. </html>

- 总结:

  • trait的5大功能:代码复用、继承上下文中的应用、实现功能扩展、同名处理、trait和接口interface组合
  • 子类同名成员优先级高于父类,子类>trait>父类
  • 可以跨文档引入接口iCreateId,trait,createId,方法:require ‘demo6.php’;
  • 接口interface中的抽象方法可放在trait中,并引入到当前工作类中,进行实例
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议