里氏替換原則(Liskov Substitution Principle, LSP)由 Barbara Liskov 於 1987 年提出,核心定義:
若對每一個類型為 T₁ 的對象 o₁,都存在類型為 T₂ 的對象 o₂,使得以 T₁ 定義的所有程序 P 在所有對象 o₁ 都替換為 o₂ 時行為不變,則 T₂ 是 T₁ 的子類型。
通俗說:子類對象必須能無縫替換父類對象,且不改變程序的正確性。
// 父類:減法計算器
class Calc {
public void calc(int a, int b) {
System.out.println(a + " - " + b + " = " + (a - b));
}
}
// 子類:覆寫為加法 —— 破壞了父類行為契約
class CalcSon extends Calc {
@Override
public void calc(int a, int b) {
System.out.println(a + " + " + b + " = " + (a + b)); // 行為改變!
}
}
// 測試
Calc c = new Calc(); c.calc(10, 20); // 輸出 10 - 20 = -10
Calc c2 = new CalcSon(); c2.calc(10, 20); // 輸出 10 + 20 = 30 —— 行為不一致!
這樣的繼承導致多態失效:父類引用指向子類對象時,語義發生根本改變,違背「is-a」關係。
addThem()),不影響父類協議。ArrayList,子類用 List)。List,子類返回 ArrayList)。將原本的繼承關係解除,改為依賴/組合或共同繼承抽象介面:
// 抽象介面
public abstract class Calculator {
public abstract void calc(int a, int b);
}
// 兩個獨立實現,互不干擾
public class SubCalc extends Calculator { // 減法
@Override public void calc(int a, int b) { ... }
}
public class AddCalc extends Calculator { // 加法
@Override public void calc(int a, int b) { ... }
public void addThem(int a, int b) { ... } // 專有方法
}
「繼承是強耦合,組合是弱耦合。只有真正滿足『is-a』且行為可替換時,才使用繼承;其餘情況優先考慮介面+組合。」
掌握 LSP 不僅能避免設計缺陷,更是寫出可維護、可擴展系統的關鍵。