首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 面向對象核心:接口與繼承的區別、協作與設計模式應用

     編輯:Java 相關知識

前言

Java 無多重繼承,但通過接口實現多重實現;繼承表現為多態。本文通過「父親打兒子」生動案例,講透繼承實現多態、接口實現功能擴展、兩者協作的設計原則(開閉原則、里氏替換),並對比修改舊功能與增加新功能的正確姿勢。

一、繼承與多態:經典案例

1. 父類定義


public class Father {
    public void hitChild() {
        System.out.println("臭崽子,你站著,不打你我不是你爹!");
    }
}

2. 三個子類重寫


public class Son1 extends Father {
    @Override public void hitChild() {
        System.out.println("為什麼打我?我做錯什麼了!");
    }
}
public class Son2 extends Father {
    @Override public void hitChild() {
        System.out.println("我知道錯了,別打了!");
    }
}
public class Son3 extends Father {
    @Override public void hitChild() {
        System.out.println("我跑,你打不著!");
    }
}

3. 多態演示


Father father = new Father(); father.hitChild(); // 父類實現
father = new Son1(); father.hitChild(); // 子類 1 實現
father = new Son2(); father.hitChild(); // 子類 2 實現
father = new Son3(); father.hitChild(); // 子類 3 實現
臭崽子,你站著,不打你我不是你爹!
為什麼打我?我做錯什麼了!
我知道錯了,別打了!
我跑,你打不著!

結論:父類引用指向不同子類對象,調用同一方法產生不同行為 —— 這就是多態。

二、接口實現多重實現:突破單繼承限制


public class Son implements Father1, Father2, Father3 { /* 相當於 C++ 多重繼承 */ }

一個類可實現多個接口,獲得多組契約能力。

三、核心設計原則:修改 vs 擴展

維度繼承接口
核心目的修改舊功能(Override 重寫實現)增加新功能(Implements 新契約)
對舊代碼影響子類可改變父類行為,風險較大不修改舊類,零風險擴展
開閉原則 (OCP)違反:修改父類/子類即修改符合:對擴展開放,對修改關閉
里氏替換 (LSP)子類必須能替換父類不破壞語義實現類必須滿足接口契約

四、實戰場景:二代子類的兩種演進路徑

場景:一代子類 Son1 已有 hitChild()(打孩子)功能

路徑 A:繼承修改舊功能(行為變更)


// 二代子類:改變「打孩子」的具體實現
public class Son11 extends Son1 {
    @Override public void hitChild() {
        System.out.println("我是二代子類對此方法的新實現");
    }
}
  • 適用:業務邏輯變更、修正 Bug、優化算法。
  • 風險:可能破壞父類契約,需嚴格測試。

路徑 B:接口增加新功能(能力擴展)


// 1. 定義新能力接口
public interface PetInterface {
    void pet(); // 寵孩子
}

// 2. 二代子類:繼承舊能力 + 實現新接口
public class Son11 extends Son1 implements PetInterface {
    @Override public void pet() {
        System.out.println("父親很愛我!");
    }
}
  • 適用:新增業務能力、整合第三方服務、插件化擴展。
  • 優勢:完全不動 Son1 代碼,零回歸風險。

五、進階:組合優於繼承

當「是一種」關係不穩固時,優先用組合/委派替代繼承:


// 繼承版(耦合緊)
class Bird extends Animal { void fly() {} }
class Penguin extends Bird { /* 企鵝不會飛,違反 LSP */ }

// 組合版(靈活)
interface Flyable { void fly(); }
class Bird { Flyable flyBehavior; }
class Eagle extends Bird { Bird() { flyBehavior = new SoarFly(); } }
class Penguin extends Bird { Bird() { flyBehavior = new NoFly(); } }

六、總結:何時用繼承,何時用接口?

  1. IS-A 關係穩定、需共享代碼/狀態 → 繼承 (extends)。
  2. CAN-DO 能力、需多重實現、插件化、跨層級復用 → 接口 (implements)。
  3. 修改現有行為 → 繼承 + Override(謹慎,遵守 LSP)。
  4. 新增行為/能力 → 接口 + Implements(首選,符合 OCP)。
  5. 疑難雜症 → 組合/委派/策略模式,解耦行為與實體。

掌握「繼承做修改,接口做擴展」這一核心直覺,配合設計原則,能讓你的類體系既靈活擴展又穩健演進,避免「繼承地獄」與「接口爆炸」兩極陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved