首頁  >  文章  >  後端開發  >  php物件導向中的抽象類別、物件介面、instanceof 和契約式程式設計教程

php物件導向中的抽象類別、物件介面、instanceof 和契約式程式設計教程

伊谢尔伦
伊谢尔伦原創
2017-06-29 09:43:121375瀏覽

物件導向程式設計(OOP)是一種電腦程式架構。 OOP的一條基本原則是電腦程式是由單一能夠扮演子程式的單元或物件組合而成。 OOP達到了軟體工程的三個主要目標:重複使用性、靈活性和擴展性。為了實現整體運算,每個物件都能夠接收訊息、處理資料和向其它物件發送訊息。

1、PHP中的抽象類別

PHP 5 支援抽象類別和抽象方法。定義為抽象的類別不能被實例化。任何一個類,如果它裡面至少有一個方法是被聲明為抽象的,那麼這個類別就必須被宣告為抽象的。被定義為抽象的方法只是聲明了其呼叫方式(參數),不能定義其特定的功能實作。在類別的宣告中使用 abstract 修飾符可以將某個類別宣告為抽象的。

可以這樣理解,抽象類別作為一個基類,它把特定的細節留給繼承者來實現。透過抽象概念,可以在開發專案中創造出擴展性很好的架構。

abstract class AbstractClass
{
    code...
}

1.1、抽象方法

使用 abstract 關鍵字定義抽象方法。抽象方法只保留方法原型(方法的定義中剔除了方法體之後的簽章),它包括存取等級、函數關鍵字、函數名稱和參數。他不包含({})或括號內部的任何程式碼。例如下面的程式碼就是一個抽象方法定義:

abstract public function prototypeName($protoParam);

繼承一個抽象類別的時候,子類別必須定義父類別中的所有抽象方法;另外,這些方法的存取控制必須和父類中一樣(或更為寬鬆)。此外方法的呼叫方式必須匹配,即類型和所需參數數量必須一致。

1.2、關於抽象類別

某個類別只要包含至少一個抽象方法就必須宣告為抽象類別
宣告為抽象的方法,在實作的時候必須包含相同的或者更低的存取等級。
不能使用 new 關鍵字建立抽象類別的實例。
被宣告為抽象的方法不能包含函數體。
如果將擴充的類別也宣告為抽象類,在擴充抽象類別時,可以不用實作所有的抽象方法。 (如果某個類別從抽象類別繼承,當它沒有實作基底類別中所宣告的所有抽象方法時,它就必須也被宣告為抽象的。)
1.3、使用抽象類別

<?php
abstract class Car
{    
    abstract function getMaxSpeend();
}
class Roadster extends Car
{
    public $Speend;
    public function SetSpeend($speend = 0)
    {
        $this->Speend = $speend;
    }
    public function getMaxSpeend()
    {
        return $this->Speend;
    }
}
class Street
{
    public $Cars ;
    public $SpeendLimit ;
    function construct( $speendLimit = 200)
    {
        $this -> SpeendLimit = $speendLimit;
        $this -> Cars = array();
    }
    protected function IsStreetLegal($car)
    {
        if ($car->getMaxSpeend() < $this -> SpeendLimit)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    public function AddCar($car)
    {
        if($this->IsStreetLegal($car))
        {
            echo &#39;The Car was allowed on the road.&#39;;
            $this->Cars[] = $car;
        }
        else
        {
            echo &#39;The Car is too fast and was not allowed on the road.&#39;;
        }
    }
}
$Porsche911 = new Roadster();
$Porsche911->SetSpeend(340);
$FuWaiStreet = new Street(80);
$FuWaiStreet->AddCar($Porsche911);
/**
 *
 * @result
 * 
 * The Car is too fast and was not allowed on the road.[Finished in 0.1s]
 *
 */
?>


2.物件介面

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

介面是透過 interface 關鍵字來定義的,就像定義一個標準的類別一樣,但其中定義所有的方法都是空的。

介面中定義的所有方法都必須是公有,這是介面的特性。

介面是一種類似類別的結構,可用來宣告實作類別所必須宣告的方法。例如,介面通常用來宣告API,而不用定義如何實作這個API。

大多數開發人員選擇在介面名稱前加上大寫字母I作為前綴,以便在程式碼和產生的文件中將其與類別區分開來。

2.1接口實作(implements)

要實作一個接口,使用implements 運算子(繼承抽象類別需要使用extends 關鍵字不同),類別中必須實作介面中定義的所有方法,否則會報一個致命錯誤。類別可以實作多個接口,用逗號來分隔多個接口的名稱。

實作多個介面時,介面中的方法不能有重名。
介面也可以繼承,透過使用 extends 運算元。
類別要實作接口,必須使用和接口中定義的方法完全一致的方式。否則會導致致命錯誤。
介面中也可以定義常數。介面常數和類別常數的使用完全相同,但是不能被子類別或子介面所覆蓋。
2.2使用介面的案例

<?php
abstract class Car
{    
    abstract function SetSpeend($speend = 0);
}
interface ISpeendInfo
{
    function GetMaxSpeend();
}
class Roadster extends Car implements ISpeendInfo
{
    public $Speend;
    public function SetSpeend($speend = 0)
    {
        $this->Speend = $speend;
    }
    public function getMaxSpeend()
    {
        return $this->Speend;
    }
}
class Street
{
    public $Cars ;
    public $SpeendLimit ;
    function construct( $speendLimit = 200)
    {
        $this -> SpeendLimit = $speendLimit;
        $this -> Cars = array();
    }
    protected function IsStreetLegal($car)
    {
        if ($car->getMaxSpeend() < $this -> SpeendLimit)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    public function AddCar($car)
    {
        if($this->IsStreetLegal($car))
        {
            echo &#39;The Car was allowed on the road.&#39;;
            $this->Cars[] = $car;
        }
        else
        {
            echo &#39;The Car is too fast and was not allowed on the road.&#39;;
        }
    }
}
$Porsche911 = new Roadster();
$Porsche911->SetSpeend(340);
$FuWaiStreet = new Street(80);
$FuWaiStreet->AddCar($Porsche911);
/**
 *
 * @result
 * 
 * The Car is too fast and was not allowed on the road.[Finished in 0.1s]
 *
 */
?>

3、類型運算子 instanceof

instanceof 運算子是PHP5 中的一個比較運算符。他接受左右兩邊的參數,並回傳一個boolean值。

確定一個PHP 變數是否屬於某個一類CLASS 的實例
檢查物件是不是從某個型別繼承
檢查物件是否屬於某個類別的實例
確定一個變數是不是實作了某個介面的物件的實例

echo $Porsche911 instanceof Car;
//result:1
echo $Porsche911 instanceof ISpeendInfo;
//result:1

4.契約程式設計

#契約式設計或Design by Contract (DbC)是一種設計電腦軟體的方法。這種方法要求軟體設計者為軟體元件定義正式的,精確的並且可驗證的接口,這樣,為傳統的抽象資料類型又增加了先驗條件、後驗條件和不變式。這種方法的名字裡用到的「契約」或是說「契約」是一種比喻,因為它和商業契約的情況有點類似。

在編寫類別之前實作聲明介面的一種程式設計實踐。這種方法在保證類別的封裝性方面非常有用。使用契約式程式設計技術,我們可以在創建應用程式之前定義視圖實現的功能,這和建築師在建造大樓之前先畫好藍圖的做法非常相似。

5.總結

抽象類別是使用 abstract 關鍵字宣告的類別。透過將某個類別標記為抽象類,我們可以推遲實現所聲明的方法。要將某個方法宣告為抽象方​​法,只要去掉包含所有大括號的方法實體,將方法宣告的程式碼行用分號結束即可。

抽象類別不能直接實例化,他們必須被繼承。

如果某個類別從抽象類別繼承,當它沒有實作基底類別中所宣告的所有抽象方法時,它就必須也被宣告為抽象的。

在介面中,我們可以宣告沒有方法體的方法原型,這點與抽象類別很相似。他們之間的差異在於,介面不能聲明任何具有方法體的方法;而且他們使用的語法也不一樣。為了將揭開規則強制加到某個類別上,我們需要使用implements關鍵字,而不是extends關鍵字。

有些情況下我們需要確定某個類別是否是特定類別的類型,或者是否實作了特定的介面。 instanceof 分成適合完成這個任務。 instanceof 檢查三件事:實例是否是某個特定的類型,實例是否從某個特定的類型繼承,實例或他的任何祖先類別是否實作類別特定的介面。

某些語言具有從多個類別繼承的能力,稱為多重繼承。 PHP不支援多重繼承。想法,他提供了為一個類別聲明多個介面的功能。

介面在宣告類別必須遵循的規則時非常有用。契約式程式設計技術使用此功能來增強封裝性,優化工作流程。

以上是php物件導向中的抽象類別、物件介面、instanceof 和契約式程式設計教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn