首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 類與物件完整指南:定義、屬性、方法、可見性、靜態、Final、魔術方法

     編輯:PHP 相關知識

前言

類是物件導向程式設計 (OOP) 的核心藍圖,封裝屬性(狀態)與方法(行為)。PHP 5 起完整支援 OOP,提供 public/protected/private 可見性、static 靜態成員、final 禁止繼承/覆寫、魔術方法等豐富機制。本文系統整理類定義、成員聲明、存取控制、靜態特性、Final 關鍵字與所有魔術方法的用法與最佳實踐。

1. 類的定義

<?php
// 1.1 空類
class EmptyClass {}

// 1.2 含屬性與方法
class Person {
    // 屬性聲明
    public string $name = '匿名';
    protected int $age = 0;
    private string $idCard = '';

    // 方法聲明
    public function sayHello(): void {
        echo "Hello, I'm {$this->name}.";
    }
}

// 1.3 Final 類:禁止被繼承
final class FinalClass {
    public function doSomething(): void {}
}

// 1.4 繼承 Final 類會報錯
// class Child extends FinalClass {} // Fatal error
?>

關鍵點

  • 使用 class 關鍵字定義。
  • final class 禁止被繼承;final 也可修飾方法(禁止覆寫),但不能修飾屬性。

2. 成員屬性聲明與可見性

<?php
class PropertyDemo {
    // 2.1 可見性關鍵字
    public    $publicProp   = '公有';      // 任何處可存取
    protected $protectedProp = '受保護';    // 本類、子類、父類可存取
    private   $privateProp  = '私有';      // 僅本類內部可存取
    var       $varProp      = '舊式公有';   // PHP 5 視同 public,不建議使用

    // 2.2 靜態屬性:屬於類而非實例,所有實例共享
    public static int $instanceCount = 0;
    private static string $secret = 'class-secret';

    // 2.3 常量:不可變,隱含 public static
    public const VERSION = '1.0.0';
    protected const INTERNAL_ID = 123;

    // 2.4 初始化規則:只能用常數表達式(PHP 8.1+ 支援 new Class())
    public string $ok1 = 'constant';
    public int    $ok2 = 1 + 2;           // 常數表達式
    // public string $bad = $this->method(); // 錯誤:非編譯期常數
    // public string $bad2 = someFunc();    // 錯誤:函數呼叫
}
?>

存取方式對照表

位置非靜態屬性靜態屬性常量
類內部 (非靜態方法)$this->propself::$prop / static::$propself::CONST
類內部 (靜態方法)不可直接存取self::$prop / static::$propself::CONST
類外部$obj->prop (需 public)ClassName::$propClassName::CONST
子類內部$this->prop (protected/public)parent::$prop / static::$propparent::CONST

晚期靜態綁定 (LSB)

static::$prop 在繼承鏈中指向實際調用的類,而 self::$prop 永遠指向定義該屬性的類。建議靜態屬性存取優先使用 static::。

3. 成員方法定義與可見性

<?php
class MethodDemo {
    public function publicMethod(): void {}
    protected function protectedMethod(): void {}
    private function privateMethod(): void {}

    // 靜態方法:只能存取靜態成員
    public static function staticMethod(): void {
        echo self::$staticProp; // 正確
        // echo $this->nonStatic; // 錯誤:靜態方法無 $this
    }

    // Final 方法:禁止子類覆寫
    final public function finalMethod(): void {}
}
?>

繼承與覆寫規則

  • 子類覆寫方法時,可見性只能放寬不能收窄(protected → public 合法,public → protected 非法)。
  • final 方法不可覆寫,private 方法不可被子類看到,故子類可定義同名方法(實為新方法)。
  • 靜態方法同樣遵循可見性與 Final 規則。

4. 物件建構與銷毀

<?php
class LifeCycle {
    public function __construct(string $name) {
        $this->name = $name;
        echo "建構: $name" . PHP_EOL;
    }

    public function __destruct() {
        echo "解構: {$this->name}" . PHP_EOL;
    }

    // 複製物件時觸發
    public function __clone() {
        $this->id = uniqid(); // 重新生成唯一識別
    }
}

$obj = new LifeCycle('A');
$obj2 = clone $obj; // 觸發 __clone
unset($obj);        // 觸發 __destruct
?>

5. 魔術方法完整清單

所有以 __ 開頭的方法均為魔術方法,必須宣告為 public。以下為常用魔術方法與觸發時機:

方法觸發時機典型用途
__construct(...$args)實例化 new Class()初始化屬性、注入依賴
__destruct()物件被銷毀 (unset、作用域結束、腳本結束)釋放資源、關閉連線、記錄日誌
__call($name, $args)呼叫不可見/不存在的實例方法動態代理、方法欄位映射
__callStatic($name, $args)呼叫不可見/不存在的靜態方法靜態工廠、動態查找
__get($name)讀取不可見/不存在的屬性虛擬屬性、延遲載入
__set($name, $value)寫入不可見/不存在的屬性資料驗證、自動轉型
__isset($name)對不可見/不存在屬性呼叫 isset()/empty()配合 __get 實作虛擬屬性存在性判斷
__unset($name)對不可見/不存在屬性呼叫 unset()清理虛擬屬性快取
__sleep()serialize($obj)返回需序列化的屬性名陣列(排除資源、連線)
__wakeup()unserialize($data)重新建立資源連線、初始化狀態
__serialize()serialize() (PHP 7.4+ 推薦)返回關聯陣列,完全控制序列化資料
__unserialize($data)unserialize() (PHP 7.4+ 推薦)從關聯陣列還原狀態
__toString()物件被當作字串使用 (echo、print、字串拼接)返回物件的字串表示
__invoke(...$args)物件被當作函數呼叫 $obj()實作可呼叫物件、閉包替代
__set_state($props)var_export($obj) (PHP 5.1+)返回重建物件的靜態方法,供 var_export 輸出可執行代碼
__debugInfo()var_dump($obj) (PHP 5.6+)控制 var_dump 輸出的屬性(隱藏敏感資訊)

魔術方法實戰範例:動態屬性與唯讀保護

<?php
class DynamicEntity {
    private array $data = [];
    private array $readonly = ['id', 'created_at'];

    public function __get(string $name) {
        return $this->data[$name] ?? null;
    }

    public function __set(string $name, $value) {
        if (in_array($name, $this->readonly, true) && isset($this->data[$name])) {
            throw new Exception("屬性 {$name} 為唯讀");
        }
        $this->data[$name] = $value;
    }

    public function __isset(string $name): bool {
        return isset($this->data[$name]);
    }

    public function __unset(string $name) {
        if (in_array($name, $this->readonly, true)) {
            throw new Exception("不可刪除唯讀屬性 {$name}");
        }
        unset($this->data[$name]);
    }
}

$e = new DynamicEntity();
$e->id = 1;           // 寫入
$e->name = 'Test';    // 寫入
echo $e->name;        // 讀取
// $e->id = 2;        // 拋出例外:唯讀
// unset($e->id);     // 拋出例外:不可刪除
?>

6. 介面與抽象類(補充)

  • interface 定義契約,方法隱含 public,可定義常量。
  • abstract class 可包含抽象方法(無主體)與具體實作,不可實例化。
  • PHP 支援多介面實作、單一類繼承。
  • Trait (trait) 實現橫向代碼復用,解決單一繼承限制。

總結

掌握 PHP 類的完整語法:可見性控制封裝邊界、靜態成員屬於類、Final 防止意外覆寫、魔術方法賦予物件動態行為。善用 __get/__set 實作虛擬屬性、__invoke 實作可呼叫物件、__serialize/__unserialize 控制序列化,能編寫出既符合封裝原則又具靈活性的現代 PHP 代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved