封裝是物件導向核心特性,PHP 透過 public、protected、private 三種可視性控制屬性與方法的存取權限。本文系統整理各種呼叫情境下的存取規則,並提供完整測試代碼。
| 存取方式 | public | protected | private |
|---|---|---|---|
類外部:ClassName::staticMethod() | ✅ | ❌ | ❌ |
類外部:$obj->method() | ✅ | ❌ | ❌ |
類內部:self::staticMethod() | ✅ | ✅ | ✅ |
子類別:parent::staticMethod() | ✅ | ✅ | ❌ |
子類別實例:$obj->method() | ✅ | ✅ | ❌ |
<?php
class A {
public static $name = 'A 的靜態屬性';
public static function pubStatic() { echo "public static\n"; }
protected static function proStatic() { echo "protected static\n"; }
private static function priStatic() { echo "private static\n"; }
}
// 類名稱呼叫靜態方法
A::pubStatic(); // ✅
// A::proStatic(); // ❌ Fatal error
// A::priStatic(); // ❌ Fatal error
// 實例呼叫 (靜態方法也可用實例呼叫)
$a = new A();
$a->pubStatic(); // ✅
// $a->proStatic(); // ❌
// $a->priStatic(); // ❌
?>
<?php
class B {
public static function test() {
self::pub(); // ✅
self::pro(); // ✅
self::pri(); // ✅
}
public static function pub() { echo "pub\n"; }
protected static function pro() { echo "pro\n"; }
private static function pri() { echo "pri\n"; }
}
B::test(); // 輸出 pub, pro, pri
?>
結論:self:: 在同一類別內可存取所有可視性成員。
<?php
class ParentClass {
public static function pub() { echo "parent pub\n"; }
protected static function pro() { echo "parent pro\n"; }
private static function pri() { echo "parent pri\n"; }
}
class ChildClass extends ParentClass {
public static function test() {
parent::pub(); // ✅
parent::pro(); // ✅
// parent::pri(); // ❌ Fatal error
}
}
ChildClass::test();
?>
結論:子類別可透過 parent:: 存取父類別 public 與 protected 靜態成員,不可存取 private。
<?php
class Base {
public function pub() { echo "pub\n"; }
protected function pro() { echo "pro\n"; }
private function pri() { echo "pri\n"; }
}
class Derived extends Base {
public function test() {
$this->pub(); // ✅
$this->pro(); // ✅
// $this->pri(); // ❌ Fatal error
}
}
$d = new Derived();
$d->test();
$d->pub(); // ✅
// $d->pro(); // ❌ (外部不可呼叫 protected)
?>
<?php
class User {
public readonly string $id; // 初始化後不可修改
public function __construct(string $id) {
$this->id = $id;
}
}
$user = new User('123');
// $user->id = '456'; // ❌ Error: Cannot modify readonly property
?>
readonly 結合 public 可替代傳統「private 屬性 + public getter」模式,程式碼更簡潔且語意明確。
掌握可視性規則是寫出高內聚、低耦合 PHP 代碼的基礎。建議在 Code Review 時檢查每個成員的可視性是否符合「最小權限原則」。