PHP 代码复用机制 trait
转载

- 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 则覆盖了被继承的方法
-
当前类成员 > 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();