介面

介紹

介面是公共 API 類必須實現的定義,以滿足介面。他們的工作是合同,指定什麼一組子類的做法,但並不怎麼他們這樣做。

介面定義與類定義非常相似,將關鍵字 class 更改為 interface

interface Foo {

}

介面可以包含方法和/或常量,但不包含任何屬性。介面常量與類常量具有相同的限制。介面方法是隱式抽象的:

interface Foo {
    const BAR = 'BAR';

    public function doSomething($param1, $param2);
}

注意: 介面不能宣告建構函式或解構函式,因為這些是類級別的實現細節。

實現

任何需要實現介面的類都必須使用 implements 關鍵字。為此,該類需要為介面中宣告的每個方法提供一個實現,並遵循相同的簽名。

單個類可以一次實現多個介面。

interface Foo {
    public function doSomething($param1, $param2);
}

interface Bar {
    public function doAnotherThing($param1);
}

class Baz implements Foo, Bar {
    public function doSomething($param1, $param2) {
        // ...
    }

    public function doAnotherThing($param1) {
        // ...
    }
}

當抽象類實現介面時,它們不需要實現所有方法。然後,必須通過擴充套件它的具體類來實現在基類中未實現的任何方法:

abstract class AbstractBaz implements Foo, Bar {
    // Partial implementation of the required interface...
    public function doSomething($param1, $param2) {
        // ...
    }
}

class Baz extends AbstractBaz {
    public function doAnotherThing($param1) {
        // ...
    }
}

請注意,介面實現是一種繼承的特性。在擴充套件實現介面的類時,你不需要在具體類中重新宣告它,因為它是隱式的。

注意: 在 PHP 5.3.9 之前,類無法實現兩個指定具有相同名稱的方法的介面,因為它會導致歧義。只要重複的方法具有相同的簽名 [1], 更新版本的 PHP 就允許這樣做。

繼承

與類一樣,可以使用相同的關鍵字 extends 在介面之間建立繼承關係。主要區別在於介面允許多重繼承:

interface Foo {

}

interface Bar {

}

interface Baz extends Foo, Bar {

}

例子

在下面的示例中,我們有一個簡單的車輛介面示例。車輛可以前進和後退。

interface VehicleInterface {
    public function forward();

    public function reverse();

    ...
}

class Bike implements VehicleInterface {
    public function forward() {
        $this->pedal();
    }

    public function reverse() {
        $this->backwardSteps();
    }

    protected function pedal() {
        ...
    }

    protected function backwardSteps() {
        ...
    }

    ...
}

class Car implements VehicleInterface {
    protected $gear = 'N';

    public function forward() {
        $this->setGear(1);
        $this->pushPedal();
    }

    public function reverse() {
        $this->setGear('R');
        $this->pushPedal();
    }

    protected function setGear($gear) {
        $this->gear = $gear;
    }

    protected function pushPedal() {
        ...
    }

    ...
}

然後我們建立兩個實現介面的類:Bike 和 Car。Bike 和 Car 內部非常不同,但兩者都是車輛,必須實現 VehicleInterface 提供的相同公共方法。

Typehinting allows methods and functions to request Interfaces. Let’s assume that we have a parking garage class, which contains vehicles of all kinds.

class ParkingGarage {
    protected $vehicles = [];

    public function addVehicle(VehicleInterface $vehicle) {
        $this->vehicles[] = $vehicle;
    }
}

Because addVehicle requires a $vehicle of type VehicleInterface—not a concrete implementation—we can input both Bikes and Cars, which the ParkingGarage can manipulate and use.