會議管理系統中 ParticipantsInDB extends DBTable。DBTable 提供 clear()、getCount()。ParticipantsInDB 覆寫 countParticipants() 只統計未刪除記錄,但繼承了 getCount()(統計所有記錄)。
客戶端呼叫 partsInDB.getCount() 期望得到有效參會者數,實際得到總記錄數——繼承了不適用的行為。
ParticipantsInDB 代表業務領域的參會者集合,可跨多資料庫。DBTable 僅代表單一資料表。ParticipantsInDB 持有 DBTable 實例,僅暴露所需方法(如 clear()),隱藏 getCount()。public class ParticipantsInDB {
private DBTable table = new DBTable("participants");
public void clear() { table.clear(); } // 代理
public int countParticipants() { /* 自有邏輯 */ }
}
優點:精確控制公開介面,避免繼承帶來的「契約污染」。
Component 含 width/height/setWidth/setHeight。Button (矩形) 需要,但 ClockComponent (圓形) 不需要卻被迫繼承。
方案 A:引入中間類 RectangularComponent extends Component,Button 繼承它,ClockComponent 直接繼承 Component。
方案 B:提取 RectangularDimension 類,Button 組合並代理之。
核心原則:若基類功能非所有子類共享,則基類設計有缺陷,須重構。
LSP:子類型必須能替換其基類型。盡量避免覆寫——覆寫往往是設計缺陷的徵兆。