PHP中的trait

PHP中的trait

一、前言

       自PHP 5.4.0起,PHP 实现了代码复用的一个方法,称为 trait。trait其字面意思是"特性"、"特点"。使用Trait关键字,可以为PHP中的类添加新的特性。

       trait 是一种为类似 PHP 的单继承语言而准备的代码复用机制。在PHP中,只能实现单继承,而trait则避免了这点。

       PHP中的traits可以理解为一组能被不同的类都能调用到的方法集合,但Traits不是类!不能被实例化。

二、实现代码 

       1)trait 定义方法

       Log.php

 

        Publish.php

 

        Answer.php

  

   2)trait 定义属性

 1 <?php
 2 trait PropertiesTrait {
 3     public $same = true;
 4     public $different = false;
 5 }
 6 
 7 class PropertiesExample {
 8     use PropertiesTrait;
 9     public $same = true; // PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
10     public $different = true; // 致命错误
11 }

注意:

       在 PHP 7.0 之前,在类里定义和 trait 同名的属性,哪怕是完全兼容的也会抛出 E_STRICT(完全兼容的意思:具有相同的访问可见性、初始默认值)。

3)多个trait

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

 1 <?php
 2 trait Hello {
 3     public function sayHello() {
 4         echo 'Hello ';
 5     }
 6 }
 7 
 8 trait World {
 9     public function sayWorld() {
10         echo 'World';
11     }
12 }
13 
14 class MyHelloWorld {
15     use Hello, World;
16     public function sayExclamationMark() {
17         echo '!';
18     }
19 }
20 
21 $o = new MyHelloWorld();
22 $o->sayHello();
23 $o->sayWorld();
24 $o->sayExclamationMark();

冲突的解决

     如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。

     为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。

 1 <?php
 2 trait A {
 3     public function smallTalk() {
 4         echo 'a';
 5     }
 6     public function bigTalk() {
 7         echo 'A';
 8     }
 9 }
10 
11 trait B {
12     public function smallTalk() {
13         echo 'b';
14     }
15     public function bigTalk() {
16         echo 'B';
17     }
18 }
19 
20 class Talker {
21     use A, B {
22         B::smallTalk insteadof A;
23         A::bigTalk insteadof B;
24     }
25 }
26 
27 class Aliased_Talker {
28     use A, B {
29         B::smallTalk insteadof A;
30         A::bigTalk insteadof B;
31         B::bigTalk as talk;
32     }
33 }

三、优先级

       Trait应用中的优先级如下:

       1)来自当前类的成员覆盖了 trait 的方法

       2)trait 覆盖了被继承的方法

      总结:类成员优先级为: 当前类>Trait>父类

四、总结

       继承的方式虽然也能解决问题,但其思路违背了面向对象的原则,显得很粗暴;多态方式也可行,但不符合软件开发中的DRY(Don't Repeat Yourself)原则,增加了维护成本。而Trait方式则避免了上述的不足之处,相对优雅的实现了代码的复用。

参考链接:

https://segmentfault.com/a/1190000008009455#item-1-3

https://www.php.net/manual/zh/language.oop5.traits.php

posted @ 2020-04-12 11:07  欢乐豆123  阅读(970)  评论(0编辑  收藏  举报