三大權限修飾符對比
| 修飾符 | 存取範圍 | 保護程度 |
public | 任意位置 (類別內、外部、繼承類) | 最低 |
protected | 類別內部 + 繼承類 | 中等 |
private | 僅限定義該成員的類別內部 | 最高 |
核心原則:看「存取位置」而非「呼叫者」
private 成員只能在「類別定義的大括號 {} 內部」被存取,走出大括號即不可存取,無論呼叫者是誰。
程式碼實戰演示
<?php
class Human {
public $mood = ''; // 公有屬性
private $money = 500; // 私有屬性
// 公有方法:提供受控存取
public function getMoney() {
return $this->money; // ✅ 類別內部可存取 private
}
// 私有方法:內部邏輯封裝
private function secret() {
echo '我那天偷吃了一塊糖';
}
// 公有方法:暴露私有行為
public function tellMe() {
$this->secret(); // ✅ 類別內部呼叫 private 方法
}
}
$lisi = new Human();
$lisi->mood = 'happy';
echo $lisi->mood . '<br>'; // ✅ 輸出: happy
echo $lisi->getMoney() . '<br>'; // ✅ 輸出: 500
// echo $lisi->money; // ❌ Fatal Error: Cannot access private property
// $lisi->secret(); // ❌ Fatal Error: Call to private method
$lisi->tellMe(); // ✅ 正常執行: 我那天偷吃了一塊糖
?>
private 進階應用場景
1. 封裝敏感資料與驗證邏輯
<?php
class BankAccount {
private $balance = 0;
private $pin;
public function __construct($initialPin) {
$this->pin = $initialPin;
}
public function deposit($amount, $inputPin) {
if ($this->verifyPin($inputPin)) {
$this->balance += $amount;
}
}
private function verifyPin($inputPin) {
return $this->pin === $inputPin;
}
public function getBalance($inputPin) {
return $this->verifyPin($inputPin) ? $this->balance : 'PIN 錯誤';
}
}
?>
2. 模板方法模式:固定演算法骨架,延遲具體實作
<?php
abstract class ReportGenerator {
// 最終方法:定義演算法流程,禁止覆寫
final public function generate() {
$this->header();
$this->body();
$this->footer();
}
// 私有方法:共用邏輯,子類不可見
private function header() {
echo "=== 報表標題 ===\n";
}
// 受保護方法:子類必須實作
abstract protected function body();
// 私有方法:共用邏輯
private function footer() {
echo "=== 報表結尾 ===\n";
}
}
class SalesReport extends ReportGenerator {
protected function body() {
echo "銷售資料內容...\n";
}
}
?>
常見誤區與最佳實踐
| 誤區 | 正確認知 |
| 子類繼承父類 private 成員 | 子類完全不可見父類 private 成員,可定義同名成員互不干擾 |
| 同類別不同實例互存取 private | 同一類別的不同實例 可以 互相存取 private 成員 |
| 反射可繞過 private | ReflectionClass 可強制存取,但屬於特殊用途 (測試/框架),非正常業務邏輯 |
最佳實踐建議
- 預設使用 private,僅在必要時放寬為 protected/public
- 透過公有方法 (Getter/Setter) 提供受控存取,內建驗證邏輯
- 內部輔助方法標記 private,明確語意:不給外部/子類呼叫
- 避免過度使用 protected,增加耦合度