萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 繼承機制完整教學:extends 關鍵字與 Admin/User 實戰範例

繼承是 OOP 實現程式碼重用與多型的核心機制。透過 extends 關鍵字,子類別自動擁有父類別的非私有成員,並可新增或覆寫功能。本文以 User/Admin 角色系統為例,詳細說明繼承語法、存取規則與實務應用。

基本繼承語法

<?php
// 父類別(基底類別)
class User {
    private string $name = '';
    
    public function __construct(array $attribs = []) {
        $this->name = $attribs['name'] ?? '';
    }
    
    public function getName(): string {
        return $this->name;
    }
}

// 子類別繼承父類別
class Admin extends User {
    // 新增父類別沒有的功能
    public function getAdmin(): string {
        return 'Administrator';
    }
}

// 使用
$kirupa = new Admin(['name' => 'Kirupa']);
echo $kirupa->getName() . '<br />'; // Kirupa(繼承自 User)
echo $kirupa->getAdmin();             // Administrator(Admin 專有)

$regular = new User(['name' => 'Regular']);
echo $regular->getName();             // Regular
// $regular->getAdmin(); // 錯誤:User 沒有此方法
?>

繼承存取規則詳解

父類別成員可見性子類別內部外部程式碼說明
public ✅ 可存取 ✅ 可存取 完全公開
protected ✅ 可存取 ❌ 不可存取 供子類別擴充
private ❌ 不可直接存取 ❌ 不可存取 僅父類別內部,子類別需透過 public/protected 方法

實務擴充:Admin 專屬功能

<?php
class Admin extends User {
    // 封鎖使用者
    public function banUser(int $userId): bool {
        // 實作封鎖邏輯...
        return true;
    }
    
    // 解封使用者
    public function unbanUser(int $userId): bool {
        // 實作解封邏輯...
        return true;
    }
    
    // 刪除內容
    public function deleteContent(int $contentId): bool {
        // 實作刪除邏輯...
        return true;
    }
    
    // 查看系統日誌
    public function viewSystemLogs(): array {
        // 實作日誌查詢...
        return [];
    }
}
?>

重要限制:單一繼承

PHP 採用單一繼承模型:一個類別只能繼承一個父類別。

<?php
// 錯誤:PHP 不支援多重繼承
// class SuperAdmin extends User, Admin { } // Fatal error

// 替代方案:介面 + Trait
interface AdminInterface {
    public function banUser(int $userId): bool;
}

trait AdminTraits {
    public function banUser(int $userId): bool { /* ... */ }
    public function unbanUser(int $userId): bool { /* ... */ }
}

class SuperAdmin extends User {
    use AdminTraits; // 組合功能
    implements AdminInterface; // 契約約束
}
?>

方法覆寫

子類別可重新定義父類別方法,改變行為:

<?php
class User {
    public function getRole(): string {
        return 'User';
    }
}

class Admin extends User {
    // 覆寫父類別方法
    public function getRole(): string {
        return 'Administrator';
    }
    
    // 仍可呼叫父類別版本
    public function getParentRole(): string {
        return parent::getRole(); // 呼叫 User::getRole()
    }
}
?>

final 關鍵字:禁止繼承與覆寫

<?php
// 禁止被繼承
final class Config {
    // ...
}

// 禁止方法被覆寫
class BaseService {
    final protected function connectDatabase(): void {
        // 核心連線邏輯,不允許子類別修改
    }
}
?>

建構子繼承行為

<?php
class User {
    public function __construct(protected string $name) {}
}

class Admin extends User {
    // 子類別若定義建構子,必須主動呼叫 parent::__construct()
    public function __construct(string $name, private string $permissionLevel) {
        parent::__construct($name); // 必須顯式呼叫
    }
}
?>
✅ 設計原則: 組合優於繼承。繼承建立強耦合「是一種」關係;組合建立鬆耦合「有一種」關係。能用組合(介面 + Trait + 委派)解決時,優先考慮組合。

繼承 vs 組合 選擇指南

場景推薦方式理由
子類別真的是父類別的特化型態繼承語意正確、自然符合 Liskov 替換原則
只需複用部分功能Trait / 組合避免繼承層級過深、減少耦合
需在執行時動態切換行為策略模式(組合)繼承為靜態結構,無法動態變更
多個類別需共享相同功能Trait / 服務類別避免建立虛假的繼承關係
copyright © 萬盛學電腦網 all rights reserved