Java 設計之初為簡化對象模型,採用單繼承機制(一個類僅能有一個直接父類)。但現實業務往往需要一個類具備多種行為特徵。接口機制的引入,不僅解決了多繼承需求,更成為實現多態、構建靈活擴展體系的基石。本文通過代碼實例深度剖析接口如何實現多繼承與多態,並對比繼承與接口在功能擴展與修改上的差異策略。
多態的本質:父類引用指向子類對象,調用同一方法呈現不同行為。經典案例:「父親打孩子」,不同兒子反應各異:
// 父類
public class Father {
public void hitChild() { }
}
// 子類 1:委屈型
public class Son1 extends Father {
@Override
public void hitChild() {
System.out.println("為什麼打我?我做錯什麼了!");
}
}
// 子類 2:認錯型
public class Son2 extends Father {
@Override
public void hitChild() {
System.out.println("我知道錯了,別打了!");
}
}
// 子類 3:逃跑型
public class Son3 extends Father {
@Override
public void hitChild() {
System.out.println("我跑,你打不著!");
}
}
// 測試多態
public class Test {
public static void main(String[] args) {
Father father;
father = new Son1(); father.hitChild(); // 輸出:為什麼打我?我做錯什麼了!
father = new Son2(); father.hitChild(); // 輸出:我知道錯了,別打了!
father = new Son3(); father.hitChild(); // 輸出:我跑,你打不著!
}
}
核心要點:父類變量引用不同子類實例,調用同名方法 hitChild() 產生差異化輸出,這就是多態的運行時綁定機制。
public class Son implements Father1, Father2, Father3 {
// 同時實現多個接口,相當於 C++ 多重繼承
}
一個類可實現多個接口,獲得多組契約方法,實現類似多重繼承的效果,卻避免了鑽石繼承等經典問題。
| 維度 | 繼承 | 接口 |
|---|---|---|
| 核心目的 | 功能修改:改寫舊功能為新功能 | 功能擴展:增加全新功能 |
| 前提條件 | 不修改舊代碼,舊功能仍可用 | 不修改舊代碼,舊功能仍可用 |
| 關係類型 | is-a(是一種) | can-do(能做某事) |
| 耦合程度 | 強耦合 | 弱耦合 |
若一代子類 Son1 的 hitChild() 實現有缺陷,需修正邏輯:
// 二代子類繼承一代,重寫方法修正行為
public class Son11 extends Son1 {
@Override
public void hitChild() {
System.out.println("我是二代子類對此方法的新實現");
}
}
適用場景:原有業務邏輯需變更,且符合「is-a」關係,子類是父類的特化版本。
若 Son1 已有「打孩子」功能,新需求要求增加「寵孩子」功能,且不能動舊代碼:
// 定義新功能契約
public interface PetInterface {
void pet(); // 新方法聲明
}
// 二代子類:繼承舊功能 + 實現新接口
public class Son11 extends Son1 implements PetInterface {
@Override
public void pet() {
System.out.println("父親很愛我!");
}
}
優勢:Son11 同時擁有舊有 hitChild() 與新增 pet(),實現功能正交擴展,完全符合開閉原則(對擴展開放,對修改關閉)。
Java 通過 單繼承 + 多接口實現 的設計,在保持類體系簡潔的同時,賦予了強大的多態表達能力與靈活擴展機制。理解繼承用於「修改舊功能」、接口用於「擴展新功能」的設計哲學差異,是編寫可維護、可擴展 Java 代碼的關鍵。