本文参考: http://php.net/language.oop5.traits
一、什么是trait
从PHP 5.4.0 开始 PHP 实现了一种新的代码复用方式 trait。
二、trait解决了什么问题
trait 的出现是为了解决类似PHP的单继承语言而准备的一种代码复用机制,让开发人员能够在不能层次结构内独立的类中复用 method。
三、跟其它语言相比,trait 有什么 好处
Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
四、该如何使用trait
- 示例1,如何使用 trait
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
trait
ezcReflectionReturnInfo {
function
getReturnType() {
/*1*/
}
function
getReturnDescription() {
/*2*/
}
}
class
ezcReflectionMethod
extends
ReflectionMethod {
use
ezcReflectionReturnInfo;
/* ... */
}
class
ezcReflectionFunction
extends
ReflectionFunction {
use
ezcReflectionReturnInfo;
/* ... */
}
?>
- 示例2 ,trait 与 class 方法优先级问题 trait 方法会覆盖基类中的方法,当前类中的方法会覆盖 trait 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
class
Base {
public
function
sayHello() {
echo
'Hello '
;
}
}
trait
SayWorld {
public
function
sayHello() {
parent::sayHello();
echo
"World!\r\n"
;
}
}
class
MyHelloWorld
extends
Base {
use
SayWorld;
}
class
MyNewHelloWorld
extends
Base{
use
SayWorld;
public
function
sayHello(){
echo
"Hello sunshine!\r\n"
;
}
}
$o
=
new
MyHelloWorld();
$o
->sayHello();
$b
=
new
MyNewHelloWorld();
$b
->sayHello();
?>
上面的代码会输出:
- 示例3 同时使用多个 trait 通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
trait
Hello {
public
function
sayHello() {
echo
'Hello '
;
}
}
trait
World {
public
function
sayWorld() {
echo
'World'
;
}
}
class
MyHelloWorld {
use
Hello, World;
public
function
sayExclamationMark() {
echo
'!'
;
}
}
$o
=
new
MyHelloWorld();
$o
->sayHello();
$o
->sayWorld();
$o
->sayExclamationMark();
?>
上面的代码会输出:
- 示例4 冲突的解决
如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
trait
A {
public
function
smallTalk() {
echo
'a'
;
}
public
function
bigTalk() {
echo
'A'
;
}
}
trait
B {
public
function
smallTalk() {
echo
'b'
;
}
public
function
bigTalk() {
echo
'B'
;
}
}
class
Talker {
use
A, B {
B::smallTalk
insteadof
A;
A::bigTalk
insteadof
B;
}
}
class
Aliased_Talker {
use
A, B {
B::smallTalk
insteadof
A;
A::bigTalk
insteadof
B;
B::bigTalk
as
talk;
}
}
?>
- 示例5 使用trait来组成trait 正如 class 能够使用 trait 一样,其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait,能够组合其它 trait 中的部分或全部成员。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
trait
Hello {
public
function
sayHello() {
echo
'Hello '
;
}
}
trait
World {
public
function
sayWorld() {
echo
'World!'
;
}
}
trait
HelloWorld {
use
Hello, World;
}
class
MyHelloWorld {
use
HelloWorld;
}
$o
=
new
MyHelloWorld();
$o
->sayHello();
$o
->sayWorld();
?>
上面例子会输出:
除了这些特性,trait 还包括 抽象成员 静态成员 静态方法 属性 等特性,可以参考 http://php.net/language.oop5.traits