PHP 抽象類別 (Abstract Class)
抽象類別是不能被實例化的類別,用來作為其他類別的基礎。抽象類別可以包含抽象方法(沒有實作)和一般方法。
定義抽象類別
<?php
abstract class Shape {
abstract public function area(): float;
abstract public function perimeter(): float;
public function describe(): string {
return "這是一個形狀";
}
}
class Rectangle extends Shape {
public function __construct(
private float $width,
private float $height
) {}
public function area(): float {
return $this->width * $this->height;
}
public function perimeter(): float {
return 2 * ($this->width + $this->height);
}
}
// $shape = new Shape(); // 錯誤:不能實例化抽象類別
$rect = new Rectangle(5, 3);
echo $rect->area(); // 15
echo $rect->perimeter(); // 16
?>
抽象方法
抽象方法只有簽名,沒有實作:
<?php
abstract class Database {
abstract public function connect(): void;
abstract public function query(string $sql): array;
abstract public function close(): void;
// 非抽象方法可以有實作
public function execute(string $sql): bool {
$this->query($sql);
return true;
}
}
class MySQLDatabase extends Database {
private $connection;
public function connect(): void {
$this->connection = mysqli_connect('localhost', 'user', 'pass', 'db');
}
public function query(string $sql): array {
$result = mysqli_query($this->connection, $sql);
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
public function close(): void {
mysqli_close($this->connection);
}
}
?>
抽象類別 vs 介面
| 特性 | 抽象類別 | 介面 |
|---|---|---|
| 實例化 | 不可 | 不可 |
| 方法實作 | 可以有 | 不可(PHP 8+ 可有預設) |
| 屬性 | 可以有 | 只能有常數 |
| 建構子 | 可以有 | 不可 |
| 繼承 | 單一 | 多重 |
| 存取修飾符 | 可以有 | 預設 public |
<?php
// 抽象類別:共享實作
abstract class Animal {
protected string $name;
public function __construct(string $name) {
$this->name = $name;
}
abstract public function speak(): string;
public function getName(): string {
return $this->name;
}
}
// 介面:定義能力
interface Swimmable {
public function swim(): void;
}
class Duck extends Animal implements Swimmable {
public function speak(): string {
return "Quack!";
}
public function swim(): void {
echo "{$this->name} is swimming\n";
}
}
?>
模板方法模式
<?php
abstract class DataExporter {
// 模板方法
final public function export(array $data): string {
$this->validate($data);
$formatted = $this->format($data);
return $this->output($formatted);
}
protected function validate(array $data): void {
if (empty($data)) {
throw new InvalidArgumentException("Data cannot be empty");
}
}
abstract protected function format(array $data): string;
abstract protected function output(string $content): string;
}
class JsonExporter extends DataExporter {
protected function format(array $data): string {
return json_encode($data);
}
protected function output(string $content): string {
return $content;
}
}
class CsvExporter extends DataExporter {
protected function format(array $data): string {
$output = [];
foreach ($data as $row) {
$output[] = implode(',', $row);
}
return implode("\n", $output);
}
protected function output(string $content): string {
return $content;
}
}
?>
實際範例
<?php
abstract class Controller {
protected array $data = [];
abstract protected function handle(): void;
public function execute(): string {
$this->before();
$this->handle();
$this->after();
return $this->render();
}
protected function before(): void {
// 前置處理
}
protected function after(): void {
// 後置處理
}
protected function render(): string {
return json_encode($this->data);
}
}
class UserController extends Controller {
protected function handle(): void {
$this->data = [
'users' => [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
]
];
}
}
$controller = new UserController();
echo $controller->execute();
?>