物件導向程式設計 (OOP) 的三大支柱為封裝、繼承、多型。本文深入淺出講解 PHP 中的封裝機制與單一繼承模型,並透過完整程式碼示範核心概念與最佳實務。
封裝將資料(屬性)與操作資料的方法(方法)結合在類別內部,透過可視性關鍵字控制外部存取權限,達到資料隱藏與安全性提升。
| 修飾詞 | 類別內部 | 子類別 | 外部程式碼 | 預設值 |
|---|---|---|---|---|
public | ✅ | ✅ | ✅ | 是(未指定時) |
protected | ✅ | ✅ | ❌ | 否 |
private | ✅ | ❌ | ❌ | 否 |
<?php
class MyClass {
public $public = 'Public'; // 公開屬性
protected $protected = 'Protected'; // 受保護屬性
private $private = 'Private'; // 私有屬性
public function sayHello() {
echo "Hello from {$this->public}!";
}
// 透過公用方法存取私有屬性(Getter/Setter 模式)
public function getPrivate() {
return $this->private;
}
public function setPrivate($value) {
$this->private = $value;
}
}
$obj = new MyClass();
echo $obj->public; // ✅ 輸出:Public
// echo $obj->protected; // ❌ Fatal Error
// echo $obj->private; // ❌ Fatal Error
// 正確方式:透過公用方法
echo $obj->getPrivate(); // ✅ 輸出:Private
$obj->setPrivate('New Value');
echo $obj->getPrivate(); // ✅ 輸出:New Value
__get() / __set() 實現動態屬性存取class DynamicProperty {
private $data = array();
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
return isset($this->data[$name]) ? $this->data[$name] : null;
}
}
$obj = new DynamicProperty();
$obj->dynamic = '動態屬性'; // 觸發 __set()
echo $obj->dynamic; // 觸發 __get(),輸出:動態屬性
PHP 採用 單一繼承 模型:一個子類別只能繼承一個父類別(extends),但可實作多個介面(implements)。
<?php
// 父類別(基類別)
class Father {
protected $name;
public function __construct($name) {
$this->name = $name;
echo "Father 建構子執行\n";
}
public function work() {
echo "{$this->name} 正在工作\n";
}
public function __destruct() {
echo "Father 解構子執行\n";
}
}
// 子類別
class Son extends Father {
// 未定義建構子 → 自動繼承父類別建構子
// 若需自訂建構子,務必呼叫 parent::__construct()
public function play() {
echo "{$this->name} 正在玩遊戲\n";
}
}
// 實例化
$father = new Father('爸爸'); // 輸出:Father 建構子執行
$father->work(); // 輸出:爸爸 正在工作
$son = new Son('兒子'); // 輸出:Father 建構子執行(繼承)
$son->work(); // 輸出:兒子 正在工作(繼承方法)
$son->play(); // 輸出:兒子 正在玩遊戲(自有方法)
__construct() 時自動呼叫父類別建構子;自定義時必須手動 parent::__construct()。parent::method()。final 的類別不可被繼承,標記 final 的方法不可被覆寫。class A extends B extends C ❌ 錯誤語法。需用介面或 Trait 替代。private:屬性盡可能私有,透過公用方法(Getter/Setter)控制存取邏輯。protected:預期子類別需存取的內部資料或方法。interface,共用實作用 Trait,減少繼承層級深度。