Table of Contents
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()
。然後,我們創建了一個繼承自 Animal
的 Dog
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
?>

為什麼這樣設計?
抽象基類(Abstract Base Class): Animal
作為一個抽象基類,定義了所有動物都應該有的基本行為,例如 makeSound()
。
具體子類(Concrete Subclasses): Dog
和 Cat
是 Animal
的具體子類,它們繼承了 Animal
的特性並提供了 makeSound()
方法的具體實現。
方法覆寫(Method Overriding): 在 Dog
和 Cat
類中,我們覆寫了 makeSound()
方法,以提供各自特有的行為。
好處是什麼?
代碼重用(Code Reusability): 通過使用繼承,Dog
和 Cat
類可以重用 Animal
類中的代碼。這減少了重複代碼,使得代碼更為簡潔。
可維護性(Maintainability): 如果未來需要更改動物的共同行為,只需要在 Animal
類中進行更改,而不需要在每一個子類中單獨修改。
可擴展性(Extensibility): 如果未來需要添加更多種動物,只需要繼承 Animal
類並提供新的 makeSound()
實現。這樣可以輕鬆地擴展程式。
多型(Polymorphism): 由於 Dog
和 Cat
都是 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,以及如何覆寫和實現抽象方法。

為什麼這樣設計?
多層繼承(Multi-level Inheritance): 在這個範例中,我們有一個 Vehicle
Abstract Class,以及一個繼承自 Vehicle
的 LandVehicle
Abstract Class。這種多層繼承允許我們更細緻地組織代碼。
方法覆寫(Method Overriding): LandVehicle
Class 覆寫了 Vehicle
Class 中的 move()
方法。這樣做是為了提供更具體的實現。
抽象與具體方法(Abstract and Concrete Methods): Vehicle
和 LandVehicle
都有抽象方法(需要子類實現的方法),但也有具體方法(已經實現的方法)。這提供了一個平衡,使得 Class 既靈活又具有一定的結構。
有什麼好處?
代碼重用(Code Reusability): 通過繼承,我們可以重用 Vehicle
和 LandVehicle
中的代碼,這減少了重複代碼。
可維護性(Maintainability): 使用 Abstract Class 和多層繼承使得代碼更容易維護。如果需要更改移動的方式,我們只需要在一個地方(如 Vehicle
或 LandVehicle
)進行更改。
可擴展性(Extensibility): 如果未來需要添加更多種交通工具(如 AirVehicle
、WaterVehicle
等),這種設計使得擴展變得非常容易。
結構清晰(Clear Structure): 這種多層繼承和方法覆寫的結構使得代碼更加組織化,更容易理解。
高度抽象(High Abstraction): 通過使用 Abstract Class,我們定義了一個高度抽象的框架,這有助於理解各個 Class 之間的關係。
實現細節隱藏(Implementation Hiding): Abstract Class 提供了一個界面,但隱藏了實現的細節。這有助於封裝和資訊隱藏。
參考文章:
- Class Abstraction
- Abstract Class – guide you on abstract classes and how to use them effectively.