繼承是物件導向核心機制之一,透過 extends 關鍵字建立子類別,實現程式碼復用與多型。本文以商品系統為例,完整展示繼承如何解決程式碼重複、子類別擴充父類別功能、建構子鏈與方法覆寫等核心概念。
<?php
header('Content-Type: text/html; charset=utf-8');
// 父類別:商品基礎模型
class ShopProduct {
public $numPages = 0;
public $playLength = 0;
public $title = '';
public $producerMainName = '';
public $producerFirstName = '';
public $price = 0;
public function __construct(
$title, $firstName, $mainName, $price,
$numPages = 0, $playLength = 0
) {
$this->title = $title;
$this->producerFirstName = $firstName;
$this->producerMainName = $mainName;
$this->price = $price;
$this->numPages = $numPages;
$this->playLength = $playLength;
}
public function getProducer() {
return "{$this->producerFirstName}{$this->producerMainName}";
}
public function getSummaryLine() {
$base = "{$this->title} ( {$this->producerMainName},";
$base .= "{$this->producerFirstName} )";
return $base;
}
}
// 子類別:書籍商品
class BookProduct extends ShopProduct {
public function getNumberOfPages() {
return $this->numPages;
}
// 覆寫父類別方法
public function getSummaryLine() {
$base = parent::getSummaryLine(); // 呼叫父類別實作
$base .= ":頁數 - {$this->numPages} )";
return $base;
}
}
// 子類別:CD 商品
class CdProduct extends ShopProduct {
public function getPlayLength() {
return $this->playLength;
}
public function getSummaryLine() {
$base = parent::getSummaryLine();
$base .= ":播放時間 - {$this->playLength} )";
return $base;
}
}
// 實例化子類別(自動呼叫父類別建構子)
$product1 = new BookProduct("PHP 物件導向", "陳", "作者", 500, 300);
$product2 = new CdProduct("PHP 入門光碟", "林", "講師", 300, 0, 120);
// 多型:統一介面處理不同子類別
$products = [$product1, $product2];
foreach ($products as $product) {
echo $product->getSummaryLine() . "<br>";
// 輸出:
// PHP 物件導向 ( 作者,陳 ):頁數 - 300 )
// PHP 入門光碟 ( 講師,林 ):播放時間 - 120 )
}
// 存取繼承的父類別方法
echo "作者:" . $product2->getProducer() . "<br>"; // 作者:林講師
子類別未定義 __construct 時自動呼叫父類別建構子。但父類別建構子包含所有子類別屬性參數,違反單一職責原則。改進方案:
class BookProduct extends ShopProduct {
public function __construct($title, $firstName, $mainName, $price, $numPages) {
// 呼叫父類別建構子,只傳遞共同屬性
parent::__construct($title, $firstName, $mainName, $price, $numPages);
// 子類別專屬初始化
}
}
parent::method() 復用父類別邏輯並擴充ShopProduct 子類別皆有 getSummaryLine()| 修飾詞 | 子類別可存取 | 外部可存取 |
|---|---|---|
| public | ✅ | ✅ |
| protected | ✅ | ❌ |
| private | ❌ | ❌ |
呼叫 $obj->method() 時:
Error (PHP 7+) 或 Fatal error