PHP 代码复用机制 trait_PHP

  • 1. trait 的介绍
  • 2. trait 的基础用法
  • 3. trait 的优先级
  • 4. trait 的 as 用法
  • 5. 引入多个 trait 时的成员同名问题

1. trait 的介绍


众所周知,PHP 是单继承的语言,也就是 PHP 中的类只能继承一个父类,无法同时从多个基类中继承属性和方法,于是 PHP 实现了一种代码复用的方法,称之为 trait,使开发人员可以在不同层次结构内独立的类中复用属性和方法

trait 不是接口也不是类,不可以被实例化也不可以被继承,只是用来将公共代码(属性和方法)提供给其他类使用的

2. trait 的基础用法


trait 的成员:trait 的成员只能有属性和方法,不能定义类常量


1. ​​// 定义一个 trait​​
2. ​​trait Say​​
3. ​​{​​
4. ​​// 在 trait 中不能定义常量​​
5. ​​// 报错提示:Traits cannot h**e constants​​
6. ​​// const PI = 3.14; // 错误示例​​
7. ​​// 属性​​
8. ​​public static $name = 'liang';​​
9. ​​// 方法​​
10. ​​public static function hello()​​
11. ​​{​​
12. ​​echo 'Hello World !';​​
13. ​​}​​
14. ​​}​​
15. ​​class User​​
16. ​​{​​
17. ​​use Say; // 在类中引入 trait​​
18. ​​}​​
19. ​​// 测试输出​​
20. ​​echo User::$name;​​
21. ​​echo User::hello();​​

3. trait 的优先级


类成员和 trait 成员同名,属性和方法有不同的处理

如果是属性同名,PHP 直接抛出致命错误,方法同名则会有优先级之分

优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法

  1. ​当前类成员 > trait 成员 > 继承的成员​

4. trait 的 as 用法



1. ​​trait User​​
2. ​​{​​
3. ​​protected function hello()​​
4. ​​{​​
5. ​​echo 'user hello';​​
6. ​​}​​
7. ​​}​​
8. ​​class Person​​
9. ​​{​​
10. ​​use User {​​
11. ​​# 起别名​​
12. ​​hello as helloNewName;​​
13. ​​# 起别名并且修改方法的访问控制​​
14. ​​hello as public helloNewName;​​
15. ​​}​​
16. ​​}​​
17. ​​$o = new Person;​​
18. ​​$o->helloNewName(); // user hello​​

5. 引入多个 trait 时的成员同名问题


引入多个 trait 时,如果存在成员同名,那么 PHP 会直接抛出致命错误

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

也就是需要使用 insteadof 操作符指定使用哪个 trait 中的成员

    1. ​​trait User​​
    2. ​​{​​
    3. ​​public function hello()​​
    4. ​​{​​
    5. ​​echo 'user hello <br>';​​
    6. ​​}​​
    7. ​​}​​
    8. ​​trait Admin​​
    9. ​​{​​
    10. ​​public function hello()​​
    11. ​​{​​
    12. ​​echo 'admin hello <br>';​​
    13. ​​}​​
    14. ​​}​​
    15. ​​class Person​​
    16. ​​{​​
    17. ​​use User, Admin {​​
    18. ​​// 指定 hello 方法应用哪个 trait 上的​​
    19. ​​Admin::hello insteadof User;​​
    20. ​​// User 上的 hello 想要使用的话就定义个别名,不想使用可以不定义别名​​
    21. ​​User::hello as helloUser;​​
    22. ​​}​​
    23. ​​}​​
    24. ​​$o = new Person;​​
    25. ​​$o->hello();​​
    26. ​​$o->helloUser();​​