封裝、繼承、多態是面向對象三大支柱,也是 Java 程式設計的靈魂。本文從底層機制、代碼實戰、設計原則三個維度,透徹剖析三大特性的本質與最佳實踐。
將「變化點」隱藏,暴露「穩定介面」。使用者不需知道內部實現,只需知道「做什麼」;開發者決定「怎麼做」。
| 修飾符 | 同類 | 同包 | 子類(異包) | 非子類(異包) |
|---|---|---|---|---|
| private | ✓ | ✗ | ✗ | ✗ |
| default(無) | ✓ | ✓ | ✗ | ✗ |
| protected | ✓ | ✓ | ✓ | ✗ |
| public | ✓ | ✓ | ✓ | ✓ |
class AverageCalculator {
private int[] scores; // 隱藏資料結構
private double average; // 隱藏中間結果
public void setScores(int[] scores) { // 受控輸入
this.scores = scores.clone(); // 防禦性複製
}
public double getAverage() { // 穩定介面
if (scores == null || scores.length == 0) return 0;
int sum = 0;
for (int s : scores) sum += s;
average = (double) sum / scores.length;
return average;
}
// 內部邏輯變更(如加權平均)不影響呼叫端
}
class Animal {
private String name; // 子類不可直接存取
protected int age; // 子類可存取
public void setName(String name) { this.name = name; }
public String getName() { return name; }
}
class Dog extends Animal {
public void bark() {
System.out.println(getName() + " 汪汪"); // 必須透過 public/protected 方法
}
}
class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // 呼叫父類建構子,必須第一行
this.breed = breed; // this 指向當前物件
}
@Override
public String toString() {
return "Dog[" + super.toString() + ", breed=" + breed + "]"; // super 呼叫父類實現
}
}
需要多型(向上轉型)? ├── 是 → 是嚴格 Is-A 關係? │ ├── 是 → 父類穩定、子類變化小? → 繼承 │ └── 否 → 組合 + 介面 └── 否 → 組合
Animal animal = new Dog(); // 編譯型別 Animal,執行型別 Dog
animal.getName(); // 非靜態方法:動態分派 → 執行 Dog 的覆寫版本(若有)或 Animal 版本
animal.age; // 欄位:靜態綁定 → 存取 Animal 的 age
animal.bark(); // 編譯錯誤:Animal 無此方法
interface Payment { void pay(double amount); }
class Alipay implements Payment { public void pay(double a) { /* ... */ } }
class WechatPay implements Payment { public void pay(double a) { /* ... */ } }
class OrderService {
public void checkout(Payment payment, double amount) {
payment.pay(amount); // 不關心具體支付方式
}
}
| 陷阱 | 現象 | 解決 |
|---|---|---|
| 欄位遮蔽 | 父子同名欄位,父類參考存取父欄位 | 欄位私有化、提供 getter/setter |
| 靜態方法隱藏 | 父子同名 static 方法,編譯型別決定呼叫 | 不覆寫 static 方法、用實例方法 |
| 建構子呼叫覆寫方法 | 父類建構子呼叫被子類覆寫方法,子類欄位未初始化 | 建構子不呼叫可覆寫方法、final/private 方法安全 |
| 向下轉型風險 | ClassCastException | instanceof 守衛、Visitor 模式、設計避免向下轉型 |
// 核心介面(穩定)
interface OrderProcessor { void process(Order order); }
// 基礎實現(封裝共同邏輯)
abstract class BaseProcessor implements OrderProcessor {
protected void validate(Order order) { /* 通用驗證 */ }
protected void log(Order order) { /* 通用日誌 */ }
public final void process(Order order) { // 模板方法,final 禁止覆寫
validate(order);
doProcess(order); // 子類實現
log(order);
}
protected abstract void doProcess(Order order);
}
// 具體策略(多型擴展)
class NormalOrderProcessor extends BaseProcessor {
protected void doProcess(Order order) { /* 普通訂單邏輯 */ }
}
class VipOrderProcessor extends BaseProcessor {
protected void doProcess(Order order) { /* VIP 專屬邏輯 */ }
}
// 工廠封裝創建邏輯(封裝變化點)
class ProcessorFactory {
public static OrderProcessor create(OrderType type) {
return switch (type) {
case NORMAL -> new NormalOrderProcessor();
case VIP -> new VipOrderProcessor();
};
}
}
// 使用端(面向介面程式設計)
class OrderService {
public void handle(Order order) {
OrderProcessor processor = ProcessorFactory.create(order.getType());
processor.process(order); // 多型分派
}
}
封裝建立邊界,繼承實現複用,多態實現擴展。**高內聚、低耦合、面向介面、里氏替換、開放封閉**——這五大 SOLID 原則,皆建立在對三大特性的深度理解與克制使用之上。記住:繼承是「白銀子彈」,組合才是「黃金標準」;多型不是為了炫技,而是為了應對變化。