探索 PHP Abstract Class,物件導向就是不斷的抽象化

Shallow Focus Photo of Gray Paintbrush

PHP Abstract Class 是物件導向的重要概念,目的是抽象化設計,讓程式更靈活,也是應用設計模式很重要的實作方式。

什麼是 PHP Class

在 PHP 中,Class 是一種用來封裝相關函數和變數的藍圖或模板。當你需要創建多個具有相同特性和行為的對象時,使用 Class 非常有用。

Class 實現了物件導向三要素~

封裝(Encapsulation):

Class 可以將數據(變數)和行為(函數)封裝在一起。

繼承(Inheritance):

一個 Class 可以繼承另一個 Class。

多型(Polymorphism):

通過繼承 (Inheritance) 和介面 (Interface),不同的 Class 可以定義相同的方法。

程式範例

<?php
// 定義一個名為 "Animal" 的 Class
class Animal {
    // 定義一個變數
    public $name;

    // 定義一個函數
    public function makeSound() {
        echo "Some generic animal sound";
    }
}

// 創建一個 Animal 對象
$animal = new Animal();
$animal->name = "Dog";
$animal->makeSound();  // 輸出 "Some generic animal sound"
?>

在這個範例中,我們定義了一個名為 Animal 的 Class,並在其中加入了一個變數 $name 和一個函數 makeSound()。然後,我們創建了一個 Animal 的實例(或對象)並設定其名稱和行為。

這是一個非常精簡的 Class 範例,更多 Class 說明介紹,請參考:PHP 物件導向的基礎,從類別 (Class) 與物件 (Object) 開始

什麼是 PHP Abstract Class

Abstract Class 是一種不能被實例化(不能創建對象)的 Class。它通常包含一個或多個抽象方法,這些方法僅有聲明而無實現。

當你有一些通用的方法,但不希望該 Class 被直接實例化時,應使用 Abstract Class。

程式範例

<?php
// 定義一個名為 "Animal" 的 Abstract Class
abstract class Animal {
    // 定義一個抽象方法
    abstract public function makeSound();

    // 定義一個普通方法
    public function run() {
        echo "Running";
    }
}

// 定義一個繼承自 Animal 的 Class
class Dog extends Animal {
    public function makeSound() {
        echo "Woof";
    }
}

// 創建一個 Dog 對象
$dog = new Dog();
$dog->makeSound();  // 輸出 "Woof"
$dog->run();        // 輸出 "Running"
?>

在這個範例中,我們定義了一個名為 Animal 的 Abstract Class,並在其中定義了一個抽象方法 makeSound() 和一個普通方法 run()。然後,我們創建了一個繼承自 AnimalDog Class,並實現了 makeSound() 方法。

Class 與 Abstract Class 的差異

不同之處

  • Class 可以被實例化,而 Abstract Class 不可以。
  • Abstract Class 可以包含抽象方法,但 Class 不可以。

如何互動合作

通常,Abstract Class 作為基礎 Class,其他 Class 可以繼承它並實現其抽象方法。

程式範例

<?php
// 定義一個名為 "Animal" 的 Abstract Class
abstract class Animal {
    abstract public function makeSound();
}

// 定義一個繼承自 Animal 的 Class
class Dog extends Animal {
    public function makeSound() {
        echo "Woof";
    }
}

// 定義另一個繼承自 Animal 的 Class
class Cat extends Animal {
    public function makeSound() {
        echo "Meow";
    }
}

// 創建對象
$dog = new Dog();
$cat = new Cat();

// 輸出
$dog->makeSound();  // Woof
$cat->makeSound();  // Meow
?>
Simple PHP Abstract Class Diagram
Class Diagram

為什麼這樣設計?

抽象基類(Abstract Base Class): Animal 作為一個抽象基類,定義了所有動物都應該有的基本行為,例如 makeSound()

具體子類(Concrete Subclasses): DogCatAnimal 的具體子類,它們繼承了 Animal 的特性並提供了 makeSound() 方法的具體實現。

方法覆寫(Method Overriding): 在 DogCat 類中,我們覆寫了 makeSound() 方法,以提供各自特有的行為。

好處是什麼?

代碼重用(Code Reusability): 通過使用繼承,DogCat 類可以重用 Animal 類中的代碼。這減少了重複代碼,使得代碼更為簡潔。

可維護性(Maintainability): 如果未來需要更改動物的共同行為,只需要在 Animal 類中進行更改,而不需要在每一個子類中單獨修改。

可擴展性(Extensibility): 如果未來需要添加更多種動物,只需要繼承 Animal 類並提供新的 makeSound() 實現。這樣可以輕鬆地擴展程式。

多型(Polymorphism): 由於 DogCat 都是 Animal 類型,我們可以使用多型來處理各種不同的動物,而不需要知道它們的具體類型。

高度抽象(High Abstraction): 使用 Abstract Class,我們可以定義一個高度抽象的框架,這有助於理解各個類之間的關係,並強制子類實現某些方法。

進階 Abstract Class 範例

<?php
// 定義一個名為 "Vehicle" 的 Abstract Class
abstract class Vehicle {
    public $speed;

    // 定義一個抽象方法
    abstract public function move();

    // 定義一個普通方法
    public function setSpeed($speed) {
        $this->speed = $speed;
    }
}

// 定義一個繼承自 Vehicle 的 Abstract Class
abstract class LandVehicle extends Vehicle {
    public $wheels;

    // 覆寫 move 方法
    public function move() {
        echo "Moving on land at speed " . $this->speed;
    }

    // 定義一個新的抽象方法
    abstract public function honk();
}

// 定義一個繼承自 LandVehicle 的 Class
class Car extends LandVehicle {
    public $brand;

    // 實現 honk 方法
    public function honk() {
        echo "Honking";
    }
}

// 創建一個 Car 對象
$car = new Car();
$car->setSpeed(100);  // 設定速度
$car->move();         // 輸出 "Moving on land at speed 100"
$car->honk();         // 輸出 "Honking"
?>

在這個範例中,我們首先定義了一個名為 Vehicle 的 Abstract Class,其中包含一個抽象方法 move() 和一個普通方法 setSpeed()

然後,我們定義了一個繼承自 Vehicle 的 Abstract Class LandVehicle。在這個 Class 中,我們覆寫了 move() 方法並添加了一個新的抽象方法 honk()

最後,我們定義了一個繼承自 LandVehicle 的 Class Car,並實現了 honk() 方法。

這個範例展示了如何在多層繼承中使用 Abstract Class,以及如何覆寫和實現抽象方法。

PHP Abstract Class Diagram
Class Diagram

為什麼這樣設計?

多層繼承(Multi-level Inheritance): 在這個範例中,我們有一個 Vehicle Abstract Class,以及一個繼承自 VehicleLandVehicle Abstract Class。這種多層繼承允許我們更細緻地組織代碼。

方法覆寫(Method Overriding): LandVehicle Class 覆寫了 Vehicle Class 中的 move() 方法。這樣做是為了提供更具體的實現。

抽象與具體方法(Abstract and Concrete Methods): VehicleLandVehicle 都有抽象方法(需要子類實現的方法),但也有具體方法(已經實現的方法)。這提供了一個平衡,使得 Class 既靈活又具有一定的結構。

有什麼好處?

代碼重用(Code Reusability): 通過繼承,我們可以重用 VehicleLandVehicle 中的代碼,這減少了重複代碼。

可維護性(Maintainability): 使用 Abstract Class 和多層繼承使得代碼更容易維護。如果需要更改移動的方式,我們只需要在一個地方(如 VehicleLandVehicle)進行更改。

可擴展性(Extensibility): 如果未來需要添加更多種交通工具(如 AirVehicleWaterVehicle 等),這種設計使得擴展變得非常容易。

結構清晰(Clear Structure): 這種多層繼承和方法覆寫的結構使得代碼更加組織化,更容易理解。

高度抽象(High Abstraction): 通過使用 Abstract Class,我們定義了一個高度抽象的框架,這有助於理解各個 Class 之間的關係。

實現細節隱藏(Implementation Hiding): Abstract Class 提供了一個界面,但隱藏了實現的細節。這有助於封裝和資訊隱藏。

參考文章:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *