假設現在有一個 PHP 需求 : 有兩個完全不同的類別, 但是這兩個類別 A、B 都有一個共同名稱的方法 C, 只是方法的實作方式不同. 現在有一個函式, 可能呼叫類別 A 的 C 方法, 也可能呼叫 B 的 C 方法. 如果要去實現這個函式, 那麼可能需要寫兩個不同的函式. 但是如果我想要簡單地用一個函式去實現, 應該如何做呢? 於是, 這就用到了 PHP 的一個特性 - 介面

正式介紹之前, 我們要用一個例子, 將抽象的介面模型化, 這也就是之前介紹過的編程模型, 這有利於任何人去理解介面

現在我們要生產一部手機. 那麼, 顯示器、電池、CPU、記憶體等組成了一部手機. 一部手機必須要有這些零件, 否則將無法組成一部手機. 但是這些零件可以各有不同, 相互毫無關係. 例如顯示器, 它可以是任何供應商以不同的生產方式生產的, 只要在兼容並蓄的情況下, 它可以是任何手機的顯示器. 反之來說, 任何手機都可以用這個顯示器作為零件. 如果將這個模型轉化為程式設計, 那麼手機就是一個類別, 那些顯示器、電池、CPU 等的零部件就是類別內的方法, 如果不能實現這些方法, 或者沒有這些方法, 將無法組成這部手機, 這些方法抽象化後被定義為介面. 方法的實作方式可以不同 (也就是生產方法和生產廠商可以是不同的), 但是最後都被用於實現一部手機 (類別被實例化), 不管手機是什麼樣子的, 有什麼功能. 換句話說, 任何手機都可以用顯示器這個方法實現一些功能 (介面的呼叫)

如果你已經對介面有了概念上的了解, 那麼可以正式開始學習並且使用介面了

介面在 PHP 中有兩個關鍵字 : Interfaceimplements

首先要熟悉介面的特性 :

1. 介面可以擁有常數成員

<?php

interface Interface {

    const BUFFER = 2048;

}

2. 介面可以擁有抽象方法

<?php

interface Interface {

    public function func();

}

3. 類別支援實作多個介面

<?php

interface Interface {

 

}

interface Interface2 {

 

}

class Foo implements Interface, Interface2 {

 

}

4. 介面支援從另外一個介面衍生

<?php

interface Interface {

 

}

interface InterfaceExtends extends Interface {

 

}

5. 不可以在介面中宣告屬性成員

6. 介面不可以被實例化

7. 介面中的方法不可以被實作, 只能是抽象的方法

關於介面的介紹, 就到這裡, 下面我們通過一個實例來學習使用介面

這個實例中, 實現了 People 介面、People 類別、Teacher 類別 和 Student 類別. 其中, People、Teacher 和 Student 類別都是以 People 介面為基礎, 並且 Teacher 類別 和 Student 類別都是 People 類別的衍生

<?php
interface PeopleInterface {
    public function insertName($name);
    public function insertGender($gender);
    public function getName();
    public function getGender();
}
class People implements PeopleInterface {
    protected $name;
    protected $gender;
    public function insertName($name) {
        $this->name = $name;
    }
    public function insertGender($gender) {
        $this->gender = $gender;
    }
    public function getName() {
        return $this->name;
    }
    public function getGender() {
        return $this->gender;
    }
}
class Student extends People implements PeopleInterface {
    protected $id;
    private $data;
    public function insertID($id) {
        $this->id = $id;
    }
    public function getID() {
        return $this->id;
    }
    public function insert(PeopleInterface $people) {
        $this->data = $people->getName()." : ".$people->getGender();
    }
    public function getData() {
        return $this->data;
    }
}
class Teacher extends People implements PeopleInterface {
    protected $subject;
    public function getName() {
        return $this->name." : ".$this->subject;
    }
    public function insertSubject($subject) {
        $this->subject = $subject;
    }
    public function getSubject() {
        return $this->subject;
    }
}
$teacher = new Teacher();
$teacher->insertName("Jack");
$teacher->insertSubject("math");
$teacher->insertGender("F");
$people = new People();
$people->insertName("Amy");
$people->insertGender("M");
$student = new Student();
$student->insert($teacher);
echo $student->getData();
echo "<br />";
$student->insert($people);
echo $student->getData();

從上面這個實例可以看到, 介面中的抽象方法必須在類別中被實作, 否則就會出現錯誤

我們特別注意到 Student 類別中的 insert() 方法. 它的引數中有一個 PeopleInterface, 也就是 People 的介面. 我們看到實際在呼叫 Student 的 insert() 方法的時候, 引數是一個類別. 這個方法被呼叫了兩次, 第一次放入的是 $teacher, 第二次放入的是 $people. 實際 insert() 方法裡面呼叫了介面中存在的兩個抽象方法, getName() 和 getGender() 方法. 也就是說, 只要一個類別使用了 PeopleInterface 介面, 那麼就可以成為 insert() 方法的引數

介面的實際用途是很難用言語去表達清楚的, 如果你不是很明白的話, 建議你看完上面這段之後, 重新回到第一段去看看那個疑問. 這之後, 你再回來看看這段話, 也許你就會有所感悟

總而言之, 使用介面可以讓 PHP 編程更加靈活, 也可以減少一些重複的代碼. 而且, 你可能還可以通過介面委託他人幫你實現一些功能. 使用介面之後, 別人只要知道如何使用介面, 就可以無縫地使用你的程式碼

最後, 讓我們看一下上面那個實例的運行結果如何吧 :

PHP 進階 : 介面-Jonny'Blog