PHP 5 重寫物件模型,引入完整的面向對象特性。本文從零構建認知:類如何封裝數據與行為、屬性與方法的聲明、$this 指針機制、可見性控制、構造/析構函數、靜態成員、繼承與多態,並以可運行代碼示例驗證每個概念。
<?php
class User {
// 1. 屬性 (Properties) - 狀態
public string $username = 'Guest'; // 公有:任意位置可訪問
protected string $email = ''; // 受保護:類內部 + 子類
private int $loginAttempts = 0; // 私有:僅當前類
// 靜態屬性:屬於類,不屬於實例
public static int $totalUsers = 0;
private static array $instances = [];
// 2. 構造函數:實例化時自動調用
public function __construct(string $username, string $email) {
$this->username = $username;
$this->email = $email;
self::$totalUsers++;
self::$instances[] = $this;
}
// 析構函數:銷毀前調用
public function __destruct() {
self::$totalUsers--;
}
// 3. 方法 (Methods) - 行為
public function greet(): string {
return "Hello, {$this->username}!";
}
// $this 只能在對象上下文中使用
public function login(string $password): bool {
$this->loginAttempts++;
// 驗證邏輯...
return true;
}
// 靜態方法:無 $this,通過類名調用
public static function getTotalUsers(): int {
return self::$totalUsers;
}
// 受保護方法:子類可覆寫
protected function sendWelcomeEmail(): void {
// 發送邏輯...
}
// 私有方法:內部復用
private function sanitizeInput(string $input): string {
return htmlspecialchars(trim($input));
}
// 魔術方法:屬性重載
public function __get(string $name) {
if ($name === 'email') return $this->email; // 受控訪問
throw new Exception("Property $name not accessible");
}
public function __set(string $name, $value) {
if ($name === 'email' && filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->email = $value;
}
}
}
<?php
require_once 'User.php';
// 創建實例
$user1 = new User('Alice', 'alice@example.com');
$user2 = new User('Bob', 'bob@example.com');
// 訪問公有屬性
echo $user1->username; // Alice
$user1->username = 'AliceUpdated'; // 允許
// 訪問公有方法
echo $user1->greet(); // Hello, AliceUpdated!
// 靜態成員:類名調用
echo User::$totalUsers; // 2
echo User::getTotalUsers(); // 2
// 錯誤示範
// echo $user1->email; // Fatal: Cannot access protected property
// echo $user1->loginAttempts; // Fatal: Cannot access private property
// $user1->sanitizeInput('x'); // Fatal: Cannot call private method
// 魔術方法攔截
echo $user1->email; // alice@example.com (通過 __get)
$user1->email = 'new@example.com'; // 通過 __set 驗證後設置
<?php
class AdminUser extends User {
private array $permissions = [];
public function __construct(string $username, string $email, array $permissions = []) {
parent::__construct($username, $email); // 必須調用父構造
$this->permissions = $permissions;
}
// 覆寫父類方法
public function greet(): string {
return "[ADMIN] " . parent::greet(); // 調用父實現
}
// 新增方法
public function hasPermission(string $perm): bool {
return in_array($perm, $this->permissions);
}
// 覆寫受保護方法
protected function sendWelcomeEmail(): void {
parent::sendWelcomeEmail(); // 發送普通歡迎郵件
$this->sendAdminNotification(); // 額外通知
}
private function sendAdminNotification(): void {
// 通知超管...
}
}
// 使用
$admin = new AdminUser('SuperAdmin', 'admin@site.com', ['user.manage', 'content.delete']);
echo $admin->greet(); // [ADMIN] Hello, SuperAdmin!
echo $admin->hasPermission('user.manage') ? 'Yes' : 'No'; // Yes
// 多態:父類類型引用子類對象
function welcomeUser(User $user) {
echo $user->greet();
}
welcomeUser($user1); // Hello, AliceUpdated!
welcomeUser($admin); // [ADMIN] Hello, SuperAdmin!
| 關鍵字 | 類內部 | 子類 | 外部代碼 | 繼承時可擴大 |
|---|---|---|---|---|
public | ✓ | ✓ | ✓ | - |
protected | ✓ | ✓ | ✗ | 可改為 public |
private | ✓ | ✗ | ✗ | 不可 (每類獨有) |
self:: 綁定定義時的類 (靜態綁定),static:: 綁定調用時的類 (晚期靜態綁定 LSB)parent::__construct()mixedreadonly 關鍵字,初始化後不可修改<?php
// PHP 8.2+ 推薦寫法
readonly class DTO {
public function __construct(
public string $id,
public string $name,
public DateTimeImmutable $createdAt,
) {}
}
// 介面定義契約
interface Authenticatable {
public function authenticate(string $password): bool;
}
// Trait 復用橫切邏輯
trait Loggable {
public function log(string $message): void {
error_log("[" . date('c') . "] $message");
}
}
class Service implements Authenticatable {
use Loggable;
public function authenticate(string $password): bool {
$this->log("Auth attempt");
// ...
return true;
}
}
PHP 面向對象模型已趨成熟。核心掌握:類封裝狀態與行為、可見性控制邊界、$this 代表當前實例、繼承實現多態、靜態成員屬於類。現代開發建議:優先使用 readonly class 定義不可變數據、介面定義契約、Trait 復用橫切邏輯、嚴格類型聲明、組合優於繼承。