2025年6月10日 星期二

封裝(Encapsulation)、繼承(Inheritance)和多型(Polymorphism)的定義與實際應用場景。

 好的,這就來解釋物件導向程式設計 (OOP) 的另外三大核心原則:封裝 (Encapsulation)繼承 (Inheritance)多型 (Polymorphism),並提供它們的定義與實際應用場景。


1. 封裝 (Encapsulation)

定義

封裝 是指將資料 (屬性/狀態) 和操作資料的方法 (行為/方法) 綁定在一起,形成一個獨立的單元 (物件),並隱藏物件內部的實作細節,只透過公共介面與外部互動

簡單來說,封裝就是「把東西包起來」,讓外界只能透過特定的「門」(公開方法)來存取或修改內部的「內容」(私有屬性),而不是隨意地直接操作。

核心概念

  • 資訊隱藏 (Information Hiding): 這是封裝的關鍵。物件的內部狀態(私有屬性)不應該直接暴露給外部。
  • 介面 (Interface): 透過提供公開的方法 (Public Methods) 作為與物件互動的唯一途徑。
  • 控制存取 (Controlled Access): 透過 Getter (讀取) 和 Setter (設定) 方法,可以對資料的存取進行驗證、格式化或邏輯控制。

實際應用場景

  1. 使用者物件 (User Object):

    • 場景: 在一個使用者管理系統中,User 類別可能包含 password 屬性。
    • 應用: 我們不希望外部直接存取或修改 password
      • $password 屬性設定為 private
      • 提供 setPassword(string $password) 方法,在這個方法內部可以進行密碼的加密處理 (例如:$this->password = bcrypt($password);)。
      • 提供 checkPassword(string $inputPassword) 方法來驗證密碼,而不是直接暴露原始密碼。
    • 好處: 保護敏感資料,確保資料的一致性和安全性。
    PHP
    class User
    {
        private $name;
        private $email;
        private $password; // 私有屬性
    
        public function __construct(string $name, string $email)
        {
            $this->name = $name;
            $this->email = $email;
        }
    
        // 公開方法來設定密碼,並在內部處理加密
        public function setPassword(string $password): void
        {
            $this->password = password_hash($password, PASSWORD_BCRYPT);
        }
    
        // 公開方法來驗證密碼
        public function checkPassword(string $inputPassword): bool
        {
            return password_verify($inputPassword, $this->password);
        }
    
        // 公開方法來取得姓名 (讀取器)
        public function getName(): string
        {
            return $this->name;
        }
    
        // ... 其他公開方法
    }
    
    $user = new User("Alice", "alice@example.com");
    $user->setPassword("securepassword123");
    // $user->password = "wrongpass"; // 錯誤!無法直接存取私有屬性
    
    if ($user->checkPassword("securepassword123")) {
        echo "Password is correct.\n";
    }
    
  2. 資料庫連線物件 (Database Connection Object):

    • 場景: 在一個應用程式中,需要管理資料庫連線。
    • 應用: 可以將資料庫連線的建立、關閉、查詢執行等細節封裝在一個類別中。
      • 連線字串、憑證等可以作為私有屬性。
      • 提供 connect(), disconnect(), query() 等公開方法。
    • 好處: 呼叫者不需要知道底層是如何建立連線或執行 SQL 語句的,只需使用提供的方法。當資料庫類型改變時,只需修改 Database 類別內部,而不會影響到使用它的所有程式碼。

2. 繼承 (Inheritance)

定義

繼承 是一種機制,允許一個類別 (子類別/派生類別) 從另一個類別 (父類別/基底類別/超類別) 繼承屬性 (Properties) 和方法 (Methods)。這表示子類別可以擁有父類別的所有特性和行為,並且可以新增自己的特性或修改 (覆寫) 父類別的行為。

繼承反映了「is-a」的關係。例如,「狗是一種動物」,所以 Dog 類別可以繼承 Animal 類別。

核心概念

  • 程式碼重用 (Code Reusability): 避免重複編寫相同的程式碼。
  • 類別層次結構 (Class Hierarchy): 建立類別之間的父子關係,形成一個結構化的組織。
  • 覆寫 (Overriding): 子類別可以提供其父類別中已經存在的方法的新實作。

實際應用場景

  1. 動物分類 (Animal Classification):

    • 場景: 模擬動物的行為,如發聲、移動。
    • 應用:
      • 建立一個 Animal 父類別,包含共同的屬性 (如 name) 和方法 (如 makeSound(), move())。
      • 建立 Dog, Cat, Bird 等子類別,繼承 Animal 的屬性和方法。
      • 子類別可以覆寫 makeSound() 方法來發出各自特有的聲音 (狗叫、貓叫、鳥鳴)。
      • 子類別可以新增自己的特有方法 (如 Dogfetch())。
    • 好處: 減少重複程式碼,清晰地表達類別之間的關係。
    PHP
    class Animal
    {
        protected $name;
    
        public function __construct(string $name)
        {
            $this->name = $name;
        }
    
        public function makeSound(): void
        {
            echo "{$this->name} makes a sound.\n";
        }
    
        public function move(): void
        {
            echo "{$this->name} moves.\n";
        }
    }
    
    class Dog extends Animal // Dog 繼承 Animal
    {
        public function makeSound(): void // 覆寫父類別方法
        {
            echo "{$this->name} barks: Woof! Woof!\n";
        }
    
        public function fetch(): void // 新增自己的方法
        {
            echo "{$this->name} fetches the ball.\n";
        }
    }
    
    class Cat extends Animal // Cat 繼承 Animal
    {
        public function makeSound(): void // 覆寫父類別方法
        {
            echo "{$this->name} meows: Meow! Meow!\n";
        }
    }
    
    $dog = new Dog("Buddy");
    $cat = new Cat("Whiskers");
    
    $dog->makeSound(); // Output: Buddy barks: Woof! Woof!
    $cat->makeSound(); // Output: Whiskers meows: Meow! Meow!
    $dog->fetch();     // Output: Buddy fetches the ball.
    
  2. 使用者角色系統 (User Role System):

    • 場景: 應用程式中有多種類型的使用者 (如 Admin, Editor, Guest),它們有一些共同的行為,也有一些特有的權限。
    • 應用:
      • 建立一個 User 父類別,包含 login(), logout() 等通用方法。
      • Admin 繼承 User,並新增 manageUsers(), configureSettings() 等方法。
      • Editor 繼承 User,並新增 publishContent(), editContent() 等方法。
    • 好處: 集中管理共同行為,為不同角色提供特定功能。

3. 多型 (Polymorphism)

定義

多型 意指「多種形態」。在物件導向程式設計中,它允許不同的類別以自己的方式實作同一個介面或繼承同一個抽象類別,並且可以被視為其共同的父類別或介面類型來處理。

簡單來說,就是不同的物件可以對同一個方法呼叫做出不同的回應,這取決於它們的具體類型。

核心概念

  • 共同介面/抽象類別 (Common Interface/Abstract Class): 多型的基礎是所有參與多型的類別都實作或繼承一個共同的契約 (介面) 或抽象藍圖。
  • 統一處理 (Unified Handling): 允許程式碼以統一的方式處理不同類型的物件,而無需知道它們的具體類型。
  • 動態綁定 (Dynamic Binding / Late Binding): 在執行時 (Runtime) 決定呼叫哪個具體的方法實作。

實際應用場景

  1. 支付系統 (Payment System):

    • 場景: 一個電商網站需要支援多種支付方式 (信用卡、PayPal、行動支付等)。
    • 應用:
      • 定義一個 PaymentGatewayInterface 介面,其中包含 processPayment(float $amount) 方法。
      • 創建 CreditCardGateway, PayPalGateway, MobilePayGateway 等類別,它們都實作 PaymentGatewayInterface,並各自以自己的方式實現 processPayment 方法。
      • 訂單處理邏輯只需要接受一個 PaymentGatewayInterface 型別的參數,然後呼叫其 processPayment() 方法。
    • 好處: 系統可以輕鬆地切換或新增支付方式,而無需修改訂單處理的核心邏輯。
    PHP
    interface PaymentGatewayInterface
    {
        public function processPayment(float $amount): bool;
    }
    
    class CreditCardGateway implements PaymentGatewayInterface
    {
        public function processPayment(float $amount): bool
        {
            echo "Processing credit card payment of $" . $amount . "\n";
            // ... 實際信用卡支付邏輯
            return true;
        }
    }
    
    class PayPalGateway implements PaymentGatewayInterface
    {
        public function processPayment(float $amount): bool
        {
            echo "Processing PayPal payment of $" . $amount . "\n";
            // ... 實際 PayPal 支付邏輯
            return true;
        }
    }
    
    class OrderProcessor
    {
        public function processOrder(PaymentGatewayInterface $paymentGateway, float $totalAmount): void
        {
            echo "Starting order processing...\n";
            if ($paymentGateway->processPayment($totalAmount)) {
                echo "Payment successful! Order completed.\n";
            } else {
                echo "Payment failed. Order not completed.\n";
            }
        }
    }
    
    $orderProcessor = new OrderProcessor();
    
    $creditCard = new CreditCardGateway();
    $orderProcessor->processOrder($creditCard, 100.50); // Output: Processing credit card payment of $100.5. Payment successful!
    
    $payPal = new PayPalGateway();
    $orderProcessor->processOrder($payPal, 50.00);      // Output: Processing PayPal payment of $50.0. Payment successful!
    
  2. 日誌記錄系統 (Logging System):

    • 場景: 應用程式可能需要將日誌記錄到檔案、資料庫、控制台或雲端服務。
    • 應用:
      • 定義一個 LoggerInterface 介面,其中包含 log(string $message, string $level) 方法。
      • 創建 FileLogger, DatabaseLogger, ConsoleLogger 等類別,它們都實作 LoggerInterface,並以各自的方式將日誌寫入目的地。
      • 應用程式中只需要依賴 LoggerInterface,就可以在不同的環境或配置下使用不同的日誌實作。
    • 好處: 靈活地更換日誌儲存方式,不影響應用程式的其餘部分。
  3. 圖形繪製 (Shape Drawing):

    • 場景: 繪圖應用程式需要繪製不同形狀 (圓形、矩形、三角形)。
    • 應用:
      • 定義一個 Shape 抽象類別或 Drawable 介面,包含一個 draw() 抽象方法。
      • Circle, Rectangle, Triangle 等類別繼承 Shape 或實作 Drawable,並各自實現 draw() 方法來繪製自己的圖形。
      • 可以創建一個 array 包含不同 Shape 物件的實例,然後遍歷這個陣列,並對每個物件呼叫 draw() 方法,而不需要知道每個物件的具體類型。

這四大原則 (抽象、封裝、繼承、多型) 是物件導向程式設計的基石,它們共同協作,幫助開發者設計出更模組化、可維護、可擴展且易於測試的軟體系統。

沒有留言:

張貼留言

熱門文章