1. 程式人生 > >PHP 進階之 抽象類(abstract)、接口(interface)、Trait(特征)

PHP 進階之 抽象類(abstract)、接口(interface)、Trait(特征)

包含 中一 man ont 就是 類型 link array ike

抽象類

PHP 5 支持抽象類和抽象方法。定義為抽象的類不能被實例化。

  • 抽象方法只能在抽象類中,抽象類中可以包含非抽象方法
  • 被定義為抽象的方法只是聲明了其調用方式(參數),不能定義其具體的功能實現
  • 繼承一個抽象類的時候,子類必須定義父類中的所有抽象方法,另外,這些方法的訪問控制必須和父類中一樣(或者更為寬松)。

抽象方法給我們提供了一個很好的保護父類的方法

class Fruit { 
    private $color; 
    
    public function eat() { 
        //chew 
    } 
    
    public function setColor($c
) { $this->color = $c; } } class Apple extends Fruit { public function eat() { //chew until core } } class Orange extends Fruit { public function eat() { //peel //chew } }

上面定義了一個`水果父類` ,同時定義了兩個子類`Apple`,`Orange`,此時

$apple = new Apple(); 
$apple->eat(); //實例化Apple類,調用eat方法,這沒毛病 $fruit = new Fruit(); $fruit->eat(); //如果實例化Friut類,調用eat方法就有點奇怪了,What does that taste like???

抽象方法完美的解決了這個問題

abstract class Fruit { 
    private $color; 
    
    abstract public function eat(); 
    
    public function setColor($c) { 
        
$this->color = $c; } }

因此,如果我們需要一個類的子類都實現同一個方法,每個方法的實現方法都不同,此時可以使用抽象方法

接口

使用接口(interface),可以指定某個類必須實現哪些方法,但不需要定義這些方法的具體內容。

  • 接口中只能定義方法名(含參數),不能有方法體
  • 接口中定義的所有方法都必須是公有 (public)
  • 要實現一個接口,使用 implements 操作符,類中必須實現接口中定義的所有方法
  • 設計接口時如果不確定方法參數個數,可以使用 ...$argumens 可變參數代替,或者直接為空,子類中通過傳入可變參數或者通過 func_get_args 獲取
  • 一個類可以同時實現多個接口,實現多個接口時,接口中的方法不能有重名
  • 接口也可以繼承,通過使用 extends 操作符
  • 接口中也可以定義常量

通過接口我們可以很好的降低代碼的耦合性

例如:

我有一個數據庫,我想寫一個類去訪問我的數據庫,所以我定義了一個接口

interface Database {
function listOrders():array;    //要求次方法返回的數組
function addOrder(array $arr);      //要求次方法參數類型為數組
function removeOrder();
...
}

現在我們使用MYSQL數據庫,所以我寫了一個mysql的類

class MySqlDatabase implements Database {
function listOrders() :array{...
}

過了一段時間,我們又想改成Oracle數據庫,我們又寫了一個oracle數據庫類去實現接口

class OracleDatabase implements Database {
public function listOrders() :array{...
}

因為我們使用了接口,所有的方法(參數、返回值)都一致,我們只需要修改一行代碼即可完成切換

$database = new OracleDatabase();

Trait

從PHP的5.4.0版本開始,PHP提供了一種全新的代碼復用的概念,那就是Trait。Trait其字面意思是”特性”、”特點”,我們可以理解為,使用Trait關鍵字,可以為PHP中的類添加新的特性。

熟悉面向對象的都知道,軟件開發中常用的代碼復用有繼承和多態兩種方式。在PHP中,只能實現單繼承。而Trait則避免了這點。下面通過簡單的額例子來進行對比說明。

trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
}

class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
}

class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
}

聲明一個trait 直接使用 trait 關鍵字 + 類名即可 , 與聲明一個類相似

使用trait 使用關鍵字 use + 類名

註意:從基類繼承的成員會被 trait 插入的成員所覆蓋。優先順序是來自當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。

PHP 進階之 抽象類(abstract)、接口(interface)、Trait(特征)