PHP之Trait詳解(多繼承)
本文參考: 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