多態性允許相同介面對不同具體類別實例執行不同行為。核心優勢:程式碼依賴抽象 (介面/基類) 而非具體實現,符合依賴倒置原則 (DIP),提升彈性與可測試性。
implements 多個介面static::method() 在繼承鏈中解析至實際調用類別 (PHP 5.3+)<?php
$person = PersonFactory::getPerson($_SESSION['name']); // 回傳 David/Charles/Alejandro 實例
switch (get_class($person)) {
case 'David':
$person->addFeedback('Great Article!', 'Reader', date('Y-m-d'));
break;
case 'Charles':
$person->feedback[] = ['Reader', 'Great Editing!'];
break;
case 'Alejandro':
$person->feedback->append('Awesome JavaScript!');
break;
default:
$person->addFeedback('Yay!');
}
缺點:新增類別需修改此處、違反開放封閉原則、重複邏輯、難以測試。
<?php
interface FeedbackReceiver {
public function addFeedback(string $message, string $author, string $date): void;
}
abstract class Person implements FeedbackReceiver {
protected string $name;
public function __construct(string $name) { $this->name = $name; }
// 可提供預設實作
public function addFeedback(string $message, string $author, string $date): void {
$this->feedbacks[] = compact('message', 'author', 'date');
}
}
class David extends Person {
public function addFeedback(string $message, string $author, string $date): void {
// David 專屬邏輯:寄送 Email 通知
parent::addFeedback($message, $author, $date);
mail($this->email, "New Feedback", $message);
}
}
class Charles extends Person {
public function addFeedback(string $message, string $author, string $date): void {
// Charles 專屬:記錄至資料庫
parent::addFeedback($message, $author, $date);
DB::table('feedbacks')->insert(compact('message','author','date'));
}
}
class Alejandro extends Person {
public function addFeedback(string $message, string $author, string $date): void {
// Alejandro 專屬:推送至訊息佇列
parent::addFeedback($message, $author, $date);
Queue::push('feedback.process', compact('message','author','date'));
}
}
$person = PersonFactory::getPerson($_SESSION['name']); // 回傳 FeedbackReceiver
$person->addFeedback('Great Article!', 'Some Reader', date('Y-m-d'));
abstract class Model {
protected static string $table = '';
public static function find(int $id): ?static {
// 遲綁定:static:: 解析為實際呼叫的子類別
$table = static::$table;
$row = DB::table($table)->where('id', $id)->first();
return $row ? new static($row) : null;
}
public function save(): bool {
$data = $this->toArray();
if (isset($data['id'])) {
return DB::table(static::$table)->where('id', $this->id)->update($data);
}
$this->id = DB::table(static::$table)->insertGetId($data);
return true;
}
}
class User extends Model {
protected static string $table = 'users';
}
class Post extends Model {
protected static string $table = 'posts';
}
// 使用
$user = User::find(1);
$post = Post::find(5);
| 特性 | PHP 5 | PHP 7/8 |
|---|---|---|
| 標量型別提示 | 不支援 | 支援 (int, string, bool, float) |
| 回傳型別宣告 | 不支援 | 支援 |
| 嚴格模式 | 無 | declare(strict_types=1) |
| 介面常數可覆寫 | 不可 | 可 (PHP 8.1+) |
| readonly 屬性 | 無 | PHP 8.1+ |
| Enums | 無 | PHP 8.1+ (內建多態行為) |
execute(),排隊/撤銷/記錄interface 定義契約,而非抽象類別instanceof、get_class() 分支,改用多態調用static::) 實作 Active Record、Factory Method多態性是物件導向設計靈活性的基石,PHP 5 奠定了基礎,PHP 7/8 以強型別系統將其推向成熟。掌握多態思維,是從「寫出能跑的代碼」進階到「寫出可維護、可擴充架構」的關鍵。