Java 之父 James Gosling 曾公開表示:若重設計 Java,他會移除 實現繼承(extends),保留 介面繼承(implements)。核心原因:extends 產生強耦合,破壞靈活性。
// 僵化寫法
void g(LinkedList list) { list.add(...); }
// 靈活寫法:面向介面編程
void g(Collection c) { c.add(...); }
若需將 LinkedList 換為 HashSet,前者需修改所有參數類型,後者僅需變更 new HashSet() 一處。介面隔離了變化點。
子類與父類高度耦合,父類看似安全的修改可能導致子類行為錯誤。
class Stack extends ArrayList {
private int top = 0;
void push(Object o) { add(top++, o); }
Object pop() { return remove(--top); }
}
// 用戶調用 clear() → top 不歸零 → 後續 push 產生垃圾元素
修補需覆寫所有可變狀態的父類方法,勢必導致「拋出異常」或「空實現」,將編譯期錯誤推遲到運行期。
class Stack {
private List data = new ArrayList();
private int top = 0;
void push(Object o) { data.add(top++, o); }
Object pop() { return data.remove(--top); }
// 不暴露 List 任何方法,徹底封裝
}
再如需監控最大深度,只需組合原 Stack 而非繼承:
class MonitorableStack {
private Stack delegate = new Stack();
private int highWater = 0;
void push(Object o) {
delegate.push(o);
highWater = Math.max(highWater, delegate.size());
}
// ... 其他方法委託
}
extendsimplements + 組合/委託「繼承是強耦合,組合是鬆耦合。靈活性是現代軟體開發的核心貨幣。」