介面基本語法
<?php
interface UserInterface {
public function getName(): string;
public function setName(string $name): void;
}
// 介面只能包含:public 抽象方法、常數
interface ConfigInterface {
public const VERSION = '1.0';
public function getConfig(): array;
}
?>
類別實作介面
class User implements UserInterface {
private string $name = '';
public function getName(): string {
return $this->name;
}
public function setName(string $name): void {
$this->name = $name;
}
}
$user = new User();
$user->setName('Alice');
echo $user->getName(); // Alice
介面規則與限制
| 規則 | 說明 | 錯誤範例 |
| 方法必須為 public | 介面定義公開契約 | private function setName() → Fatal error |
| 不能有方法主體 | 純規範,無實作 | function getName() {} → Fatal error |
| 可定義常數 | 介面常數自動為 public static final | - |
| 不能定義屬性 | PHP 8.0+ 可用 trait 解決 | public $name; → Fatal error |
| 支援多重實作 | class A implements I1, I2 | - |
| 介面可繼承介面 | interface B extends A | - |
抽象類別 vs 介面
| 特性 | 抽象類別 | 介面 |
| 方法實作 | 可有具體方法 | 僅抽象方法(PHP 8+ 可有預設實作) |
| 屬性 | 可定義 | 不可 |
| 建構子 | 可定義 | 不可 |
| 繼承 | 單一繼承 | 多重實作 |
| 存取修飾 | public/protected/private | 僅 public |
| 用途 | 共享程式碼、基底類別 | 定義契約、多型 |
PHP 8.0+ 新特性:介面預設實作
interface LoggerInterface {
public function log(string $msg): void;
// PHP 8.0+ 允許預設實作
public function info(string $msg): void {
$this->log('[INFO] ' . $msg);
}
}
class FileLogger implements LoggerInterface {
public function log(string $msg): void {
file_put_contents('app.log', $msg . PHP_EOL, FILE_APPEND);
}
// 繼承 info() 預設實作,可選擇覆寫
}
實務設計模式
- 依賴介面而非實作:建構子型別提示用介面
- 介面隔離原則 (ISP):拆分細粒度介面,避免巨大介面
- 標記介面:無方法介面,如
Serializable、Countable
- 契約測試:針對介面寫測試,實作類別自動符合
原始來源:www.111cn.net