天天看點

【PHP進階學習】——Trait代碼複用類

前言

衆所周知,一直以來PHP和很多語言一樣是單繼承的語言,但是常常在編碼過程中,我們需要在目前類中使用兩個或兩個以上的其他類的方法,這種情況下繼承就不能實作,而往往采用new方式執行個體化很多要用到的類,這樣就會很影響代碼的結構和開發規範。于是Trait類誕生了,它是一種代碼複用的文法,能夠實作一個類中引用多個其他類的方法。

一、概念

PHP官方手冊對Trait的描述是:

Trait是為類似PHP的單繼承語言而準備的一種代碼複用機制。Trait為了減少單繼承語言的限制,使開發人員能夠自由地在不同層次結構内獨立的類中複用method。Trait和Class組合的語義定義了一種減少複雜性的方式,避免傳統多繼承和Mixin類相關典型問題。

Trait和Class相似,但僅僅旨在用細粒度和一緻的方式來組合功能。無法通過trait自身來執行個體化。它為傳統繼承增加了水準特性的組合;也就是說,應用的幾個Class之間不需要繼承。

二、Trait類的使用

簡單地講,Trait就是一種不同于繼承的文法,定義一個trait類,在其他類中使用它則是采用use關鍵字,有點類似于命名空間的用法,但是含義不同。use關鍵字在一個類中引入Trait類後,相當于require或include了一段代碼進來,不同之處在于use的Trait類與目前類是可以看做同一個類的,即目前類可以用$this關鍵字調用Trait類的方法。

以下是原了解釋:

【PHP進階學習】——Trait代碼複用類

可以看出目前類可以簡單地use兩個Trait類,并調用其中的方法,而不僅限于繼承,隻能使用一個父類的方法。

三、Trait類的通路控制

我們知道,繼承的方式,如果基類是private修飾控制的,則子類是無法調用的。但是Trait不一樣,因為它類似于Require到目前類中了,是以不管是public、protected或private都是可以直接使用的。示例如下:

【PHP進階學習】——Trait代碼複用類

四、Trait類的優先級控制

Trait類與目前使用類、繼承的基類之間的調用優先級順序如下:

目前使用類>Trait類>繼承的基類

當存在同名方法時,會根據優先級覆寫掉同名的類。具體示例如下:

1、Trait類覆寫基類

【PHP進階學習】——Trait代碼複用類

2、目前類覆寫Trait類

【PHP進階學習】——Trait代碼複用類

五、多個Trait類的沖突控制

在PHP中,如果目前類use了兩個Trait類,同時兩個trait類都存在一個同名的方法,此時如果沒有明确解決沖突将會産生一個緻命錯誤。

對于這種情況,PHP官方給出了兩個解決方案:

1、insteadof關鍵字:通過該關鍵字指定方法名沖突時該使用哪個Trait類的方法,即:

如果C類use了A、B兩個Trait類,且A、B兩個類都存在a、b方法,則在C類use A、B類時使用insteadof聲明沖突的解決方法即可:

use A, B {

    B::a insteadof A; //a方法沖突時使用B類的a方法而不使用A類的a方法

    A::b insteadof B; //b方法沖突時使用A類的b方法而不使用B類的b方法

}

2、as關鍵字:通過as關鍵字将同名方法指定為一個别名,且僅作用于目前類中。示例如下:

use A, B {

    B::a as c; //聲明B類的a方法為c,作用于該類

    A::b as d; //聲明A類的b方法為d,作用于該類

}

六、與繼承、直接執行個體化的差別

對于目前一個類需要用到另一個或多個類的方法的情況,我們一般會想到的方式有繼承、直接執行個體化另外一個或多個類等等的方法,下面來對比一下這些方法和Trait類的差別:

1、繼承方式:對于繼承,可以完美地複用另一個類的一些方法,但是對于需要複用多個類的方法時,PHP是不支援多繼承的,而且隻能通路public和protected方法;

2、與直接執行個體化的差別:我們也可以在目前類中直接執行個體化要用到的A類與B類,但是這種方法在控制通路範圍反面,隻允許通路A、B類中public的方法;

3、使用Trait類則完全将A、B兩個類的方法導入到目前類中,可以視為目前類的一部分,唯一差別是可以存在于目前類同名的方法,此時由優先級順序來控制。