介面
介紹
介面是公共 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.