php中的trait

 

php中的trait

PHP5.4起,新增一种新的代码复用的方法,trait。PHP与JAVA类似,与C++不同,是一种单继承语言,PHP引入trait,可以减少单继承语言的限制,使开发人员能够自由地在不同的层次结构内独立的类中复用method。Trait和Class组合的语义定义了一种减少复杂性的方式,避免传统多继承和Mixin类相关经典问题,例如C++中的钻石危机(也称棱形问题):
  1. 如果在一个子类继承的多个父类中拥有相同名字的实例变量,子类在引用该变量时将产生歧义,无法判断应该使用哪个父类的变量。
  2. 如果在一个子类继承的多个父类中拥有相同方法,子类中有没有覆盖该方法,那么调用该方法时将产生歧义,无法判断应该调用哪个父类的方法。

Trait和Class相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过trait自身来实例化。它为传统继承增加了水平特性的组合。

Trait使用case

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public $a = 100;  
  5.     public function test1() {  
  6.         echo "Mytrait Test1\n";  
  7.     }     
  8.     public static function test2() {  
  9.         echo "Mytrait Test2\n";  
  10.     }     
  11.   
  12. }  
  13.   
  14. class TraitExample1 {  
  15.     use Mytrait;  
  16. }  
  17.   
  18. $obj = new TraitExample1();  
  19. $obj->test1();  
  20. TraitExample1::test2();  
  21. echo $obj->a . "\n";  

优先级

对于方法:
当前类的成员>trait的方法>从基类继承的成员

对于变量:
当前类和基类中不能存在与trait重名的变量,否则会抛出fatal error。


[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public $a = 100;  
  5.     public function test1() {  
  6.         echo "Mytrait Test1\n";  
  7.     }     
  8.     public static function test2() {  
  9.         echo "Mytrait Test2\n";  
  10.     }     
  11.   
  12. }  
  13. class Base {  
  14.     public function test1() {  
  15.         echo "Base Test1\n";  
  16.     }     
  17.     public static function test2() {  
  18.         echo "Base Test2\n";  
  19.     }     
  20.     public static function test3() {  
  21.         echo "Base Test3\n";  
  22.     }     
  23.       
  24. }  
  25. class TraitExample1 extends Base{  
  26.     use Mytrait;  
  27.     public function test1() {  
  28.         echo "TraitExample1 Test1\n";  
  29.     }     
  30.   
  31. }  
  32.   
  33. $obj = new TraitExample1();  
  34. $obj->test1();  
  35. TraitExample1::test2();  
  36. $obj->test3();  
  37. echo $obj->a . "\n";  

多个trait

通过逗号分隔,在use声明中列出多个trait,可以都插入到一个类中。

如果两个trait都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。为了解决多个trait在同一个类中的命名冲突,需要使用insteadof操作符来明确指定使用冲突方法中的哪一个。或者使用as操作符,可以将其中一个冲突的方法以另一个名称来引入。

同样的,如果两个trait有同名的变量,如果该属性的定义兼容(同样的可见性及初始值)错误级别是E_STRICT,否则错误级别是E_ERROR.

且不能通过解决方法冲突的方式解决。

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public $a = 100;  
  5.     public function test1() {  
  6.         echo "Mytrait Test1\n";  
  7.     }     
  8.     public static function test2() {  
  9.         echo "Mytrait Test2\n";  
  10.     }     
  11.   
  12. }  
  13. trait Mytrait2 {  
  14.     public function test1() {  
  15.         echo "Mytrait2 Test1\n";  
  16.     }     
  17.     public static function test2() {  
  18.         echo "Mytrait2 Test2\n";  
  19.     }     
  20.   
  21. }  
  22. class TraitExample1{  
  23.     use Mytrait,Mytrait2 {  
  24.         Mytrait::test1 insteadof Mytrait2;  
  25.         Mytrait2::test2 insteadof Mytrait;  
  26.         Mytrait::test2 as test2_2;  
  27.     }     
  28. }  
  29.   
  30. $obj = new TraitExample1();  
  31. $obj->test1();  
  32. TraitExample1::test2();  
  33. $obj->test2_2();  
  34. echo $obj->a . "\n";  

修改方法的访问控制

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public function test1() {  
  5.         echo "Mytrait Test1\n";  
  6.     }     
  7.     public function test2() {  
  8.         echo "Mytrait Test2\n";  
  9.     }     
  10.     private function test3() {  
  11.         echo "Mytrait Test3\n";  
  12.     }     
  13.   
  14. }  
  15. class TraitExample1{  
  16.     use Mytrait {  
  17.         test1 as protected;  
  18.         test2 as public test2_1;  
  19.         test3 as public;  
  20.     }     
  21. }  

指定alias会创建一个新的方法,原方法访问控制权限不变。不仅可以缩小权限的方向修改(public->private),也可以向放大权限的修改(private->public).


从trait来组成trait

与Class中使用多个trait类似,trait也可以使用多个trait。冲突的解决方式也一致。

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public function test1() {  
  5.         echo "Mytrait Test1\n";  
  6.     }     
  7.     public function test2() {  
  8.         echo "Mytrait Test2\n";  
  9.     }     
  10.   
  11. }  
  12. trait Mytrait2 {  
  13.     public function test1() {  
  14.         echo "Mytrait2 Test1\n";  
  15.     }     
  16.     public function test2() {  
  17.         echo "Mytrait2 Test2\n";  
  18.     }     
  19.   
  20. }  
  21.   
  22. trait Mytrait3 {  
  23.     use Mytrait, Mytrait2 {  
  24.         Mytrait::test1 insteadof Mytrait2;  
  25.         Mytrait2::test2 insteadof Mytrait;  
  26.     }     
  27. }  
  28. class TraitExample1{  
  29.     use Mytrait3;  
  30. }  
  31.   
  32. $obj = new TraitExample1();  
  33. $obj->test1();  
  34. $obj->test2();  

Trait的抽象成员

为了对使用的类施加强制要求,trait支持抽象方法的使用。

Trait的静态成员

trait可以定义静态变量,静态方法。

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. trait Mytrait {  
  4.     public static $in = 10;   
  5.     public function test1() {  
  6.         echo "Mytrait Test1\n";  
  7.     }     
  8.     public function test2() {  
  9.         echo "Mytrait Test2\n";  
  10.     }     
  11.   
  12. }  
  13. trait Mytrait2 {  
  14.     public function test1() {  
  15.         echo "Mytrait2 Test1\n";  
  16.     }     
  17.     public static function test2() {  
  18.         echo "Mytrait2 Test2\n";  
  19.     }     
  20.   
  21. }  
  22.   
  23. trait Mytrait3 {  
  24.     use Mytrait, Mytrait2 {  
  25.         Mytrait::test1 insteadof Mytrait2;  
  26.         Mytrait::test2 insteadof Mytrait2;  
  27.         Mytrait2::test2 as test3;  
  28.     }     
  29. }  
  30. class TraitExample1{  
  31.     use Mytrait3;  
  32. }  
  33.   
  34. $obj = new TraitExample1();  
  35. $obj->test1();  
  36. $obj->test2();  
  37. TraitExample1::test3();  
  38. [root@hadoop1 php]# cat trait2.php      
  39. <?php  
  40.   
  41. trait Mytrait {  
  42.         public static $in = 10;  
  43.         public function test1() {  
  44.                 echo "Mytrait Test1\n";  
  45.         }  
  46.         public function test2() {  
  47.                 echo "Mytrait Test2\n";  
  48.         }  
  49.   
  50. }  
  51. trait Mytrait2 {  
  52.         public function test1() {  
  53.                 echo "Mytrait2 Test1\n";  
  54.         }  
  55.         public static function test2() {  
  56.                 echo "Mytrait2 Test2\n";  
  57.         }  
  58.   
  59. }  
  60.   
  61. trait Mytrait3 {  
  62.         use Mytrait, Mytrait2 {  
  63.                 Mytrait::test1 insteadof Mytrait2;  
  64.                 Mytrait::test2 insteadof Mytrait2;  
  65.                 Mytrait2::test2 as test3;  
  66.         }  
  67. }  
  68. class TraitExample1{  
  69.         use Mytrait3;  
  70. }  
  71.   
  72. $obj = new TraitExample1();  
  73. $obj->test1();  
  74. $obj->test2();  
  75. TraitExample1::test3();  
  76. echo TraitExample1::$in;  











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值