PHP trait解析

gopher PHP 141 次浏览 , 没有评论

前言

PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。众所周知,PHP 中是单继承的,trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 methodtrait Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承问题。trait Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

一个简单的例子

首先我们举个例子来介绍 trait,和类定义相似,但使用关键字 trait 定义。在类中使用 use 组合。

  1. <?php
  2. trait T
  3. {
  4. public function m1()
  5. {
  6. return 'm1';
  7. }
  8.  
  9. public function m2()
  10. {
  11. return 'm2';
  12. }
  13. }
  14.  
  15. class Demo
  16. {
  17. use T;
  18.  
  19. public function test()
  20. {
  21. return 'test';
  22. }
  23. }
  24.  
  25. $demo = new Demo;
  26. echo $demo->m1(), PHP_EOL;
  27. echo $demo->test(), PHP_EOL;

多个trait

  1. <?php
  2.  
  3. trait T
  4. {
  5. public function m1()
  6. {
  7. return 'm1';
  8. }
  9.  
  10. public function m2()
  11. {
  12. return 'm2';
  13. }
  14. }
  15.  
  16. trait T2
  17. {
  18. public function m3()
  19. {
  20. return 'm3';
  21. }
  22. }
  23.  
  24. class Demo
  25. {
  26. use T, T2;
  27.  
  28. public function test()
  29. {
  30. return 'test';
  31. }
  32. }
  33.  
  34. $demo = new Demo;
  35. echo $demo->m1(), PHP_EOL;
  36. echo $demo->m3(), PHP_EOL;
  37. echo $demo->test(), PHP_EOL;

多个 trait 冲突解决

如果使用多个 trait,但是出现了方法名相同,这是就出现了冲突,就要手动指定使用哪个 trait 的方法,使用 insteadof 关键字实现。

  1. <?php
  2.  
  3. trait T
  4. {
  5. public function m1()
  6. {
  7. return 'm1';
  8. }
  9.  
  10. public function m2()
  11. {
  12. return 'm2';
  13. }
  14. }
  15.  
  16. trait T2
  17. {
  18. public function m1()
  19. {
  20. return 'm3';
  21. }
  22. }
  23.  
  24. class Demo
  25. {
  26. use T, T2 {
  27. // 使用 T 的 m1 方法
  28. T::m1 insteadof T2;
  29. }
  30.  
  31. public function test()
  32. {
  33. return 'test';
  34. }
  35. }
  36.  
  37. $demo = new Demo;
  38. echo $demo->m1(), PHP_EOL;
  39. echo $demo->test(), PHP_EOL;

在冲突的时候,也可以使用 use 定义方法别名解决冲突,例子如下:

  1. <?php
  2.  
  3. trait T
  4. {
  5. public function m1()
  6. {
  7. return 'm1';
  8. }
  9.  
  10. public function m2()
  11. {
  12. return 'm2';
  13. }
  14. }
  15.  
  16. trait T2
  17. {
  18. public function m1()
  19. {
  20. return 'm3';
  21. }
  22. }
  23.  
  24. class Demo
  25. {
  26. use T, T2 {
  27. T::m1 insteadof T2;
  28. T2::m1 as new_m1;
  29. }
  30.  
  31. public function test()
  32. {
  33. return 'test';
  34. }
  35. }
  36.  
  37. $demo = new Demo;
  38. echo $demo->m1(), PHP_EOL;
  39. echo $demo->new_m1(), PHP_EOL;
  40. echo $demo->test(), PHP_EOL;

改变访问权限

也可以使用 use 关键字来改变方法的访问权限。

  1. <?php
  2.  
  3. trait T
  4. {
  5. public function m1()
  6. {
  7. return 'm1';
  8. }
  9.  
  10. public function m2()
  11. {
  12. return 'm2';
  13. }
  14. }
  15.  
  16. class Demo
  17. {
  18. use T {
  19. m2 as protected;
  20. }
  21.  
  22. public function test()
  23. {
  24. return 'test';
  25. }
  26. }
  27.  
  28. $demo = new Demo;
  29. echo $demo->m1(), PHP_EOL;
  30. echo $demo->m2(), PHP_EOL;
  31. echo $demo->test(), PHP_EOL;

上面我只是介绍了一些常用的特性,详细可参考 官方手册

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Go