PHP 5 起完整支援物件導向程式設計(OOP)。本文從類的聲明、屬性與方法定義、物件實例化、訪問控制到建構子/解構子,系統講解 PHP OOP 核心概念與實戰代碼。
<?php
/**
* 計算機類:演示基本類結構
*/
class Calculator {
// 1. 屬性(成員變量)—— 可加訪問修飾符
public $brand = 'Generic'; // 公有:隨處可訪問
protected $model = 'Basic'; // 受保護:類內部及子類可訪問
private $serialNumber; // 私有:僅本類內部可訪問
// 2. 建構子:物件創建時自動調用
public function __construct($serial = '') {
$this->serialNumber = $serial ?: uniqid('SN_');
}
// 3. 方法(成員函數)
public function add(float $a, float $b): float {
return $a + $b;
}
public function subtract(float $a, float $b): float {
return $a - $b;
}
public function multiply(float $a, float $b): float {
return $a * $b;
}
public function divide(float $a, float $b): float {
if ($b == 0) {
throw new InvalidArgumentException('除數不能為零');
}
return $a / $b;
}
// 4. 存取器(Getter/Setter)封裝私有屬性
public function getSerialNumber(): string {
return $this->serialNumber;
}
// 5. 解構子:物件銷毀前自動調用
public function __destruct() {
// 釋放資源、關閉連線等收尾工作
}
}
<?php
require_once 'Calculator.php';
// 1. 實例化:使用 new 關鍵字
$calc = new Calculator('CALC-2024-001');
// 2. 訪問公有屬性
echo "品牌: {$calc->brand}\n"; // Generic
// 3. 調用公有方法
echo "5 + 3 = {$calc->add(5, 3)}\n"; // 8
echo "10 - 4 = {$calc->subtract(10, 4)}\n"; // 6
echo "6 * 7 = {$calc->multiply(6, 7)}\n"; // 42
echo "20 / 4 = {$calc->divide(20, 4)}\n"; // 5
// 4. 透過存取器讀取私有屬性
echo "序列號: {$calc->getSerialNumber()}\n"; // CALC-2024-001
// 5. 錯誤處理示例
try {
$calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "錯誤: {$e->getMessage()}\n"; // 除數不能為零
}
| 修飾符 | 類內部 | 子類 | 外部代碼 | 適用場景 |
|---|---|---|---|---|
public | ✅ | ✅ | ✅ | 對外公開的 API、介面 |
protected | ✅ | ✅ | ❌ | 內部邏輯、子類擴展點 |
private | ✅ | ❌ | ❌ | 核心數據、實現細節封裝 |
<?php
class MathUtils {
// 類常量
public const PI = 3.141592653589793;
// 靜態屬性:屬於類,不屬於實例
private static $callCount = 0;
// 靜態方法:無需實例化即可調用
public static function circleArea(float $radius): float {
self::$callCount++;
return self::PI * $radius * $radius;
}
public static function getCallCount(): int {
return self::$callCount;
}
}
// 使用方式
echo MathUtils::PI; // 3.14159...
echo MathUtils::circleArea(5); // 78.5398...
echo MathUtils::getCallCount(); // 1
<?php
// 父類
abstract class Shape {
protected $color;
public function __construct(string $color) {
$this->color = $color;
}
// 抽象方法:強制子類實現
abstract public function area(): float;
public function getColor(): string {
return $this->color;
}
}
// 子類
class Circle extends Shape {
private $radius;
public function __construct(string $color, float $radius) {
parent::__construct($color);
$this->radius = $radius;
}
public function area(): float {
return M_PI * $this->radius ** 2;
}
}
class Rectangle extends Shape {
private $width, $height;
public function __construct(string $color, float $width, float $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function area(): float {
return $this->width * $this->height;
}
}
// 多態使用
$shapes = [
new Circle('紅', 5),
new Rectangle('藍', 4, 6),
];
foreach ($shapes as $shape) {
echo "{$shape->getColor()} 形狀面積: {$shape->area()}\n";
}
<?php
interface LoggerInterface {
public function log(string $level, string $message): void;
}
class FileLogger implements LoggerInterface {
public function log(string $level, string $message): void {
file_put_contents('app.log', "[{$level}] {$message}\n", FILE_APPEND);
}
}
class DatabaseLogger implements LoggerInterface {
public function log(string $level, string $message): void {
// 寫入資料庫邏輯
}
}
// 依賴注入:面向介面編程
class Application {
private $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function run(): void {
$this->logger->log('INFO', '應用啟動');
}
}
$app = new Application(new FileLogger());
$app->run();
declare(strict_types=1) + 參數/返回類型提示readonly (PHP 8.1+)、無 Setterrequire_once掌握 PHP 物件導向精髓,能讓代碼更模組化、可測試、可維護。建議從簡單類開始練習,逐步引入設計模式(工廠、策略、觀察者等),並配合現代框架(Laravel、Symfony、ThinkPHP)的容器與服務提供者機制,構建企業級應用架構。