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

《Java 編程思想》讀書筆記(九):多態深度解析與設計原則

     編輯:Java 綜合教學

《Java 編程思想》讀書筆記(九):多態深度解析與設計原則

多態是繼承與抽象之後的第三大 OOP 基石,實現「接口與實現分離」、「何謂」與「如何做」解耦,使代碼可擴展、可維護。

1. 向上轉型

子類對象賦值給父類引用,自動發生,無需強轉。例:Instrument i = new Wind();。tune(Instrument) 可接收任何子類,避免為每種樂器寫重載方法。

class Instrument { void play(Note n) { ... } }
class Wind extends Instrument { void play(Note n) { ... } } // 覆蓋
void tune(Instrument i) { i.play(Note.MIDDLE_C); } // 多態調用
Wind flute = new Wind();
tune(flute); // 向上轉型,動態綁定調用 Wind.play()

2. 動態綁定機制

  • 早期綁定:編譯期確定調用目標(C/C++ 非 virtual 函數)
  • 晚期綁定(動態綁定):運行期根據對象真實類型分派方法。Java 默認所有非 final/private/static 方法動態綁定
  • final 方法禁止覆蓋,編譯器可內聯優化

3. 經典「形狀」例子

class Shape { void draw(); void erase(); }
class Circle extends Shape { void draw() { println("Circle.draw"); } ... }
class Square extends Shape { ... }
class Triangle extends Shape { ... }

Shape[] shapes = new Shape[9];
for (int i=0; i

輸出隨機,證明編譯期無法知曉具體類型,完全靠運行期分派。

4. 擴展性

新增 Brass extends Wind、Woodwind extends Wind 等,tune()、tuneAll() 零修改 即可支持新類型。這就是「將變化隔離」的威力。

5. 覆蓋 vs 重載陷阱

class InstrumentX { void play(int noteX) { ... } }
class WindX extends InstrumentX { void play(NoteX n) { ... } } // 參數類型不同 → 重載!

調用 tune(InstrumentX).play(NoteX.MIDDLE_C) 時,實參是 int,匹配父類 play(int),子類版本不被調用。覆蓋必須參數列表完全一致,建議加 @Override 註解編譯期檢查。

6. 抽象類與抽象方法

  • abstract void play(); 只有聲明無實現,強制子類實現
  • 含抽象方法的類必須聲明 abstract
  • 抽象類可包含具體方法與字段,接口更純粹(Java 8 前)

7. 接口:純抽象契約與多重實現

  • interface Instrument5 { void play(); String what(); void adjust(); }
  • 字段默認 public static final,方法默認 public
  • 多重實現:class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly —— 單繼承 + 多實現,解決 C++ 多重繼承菱形問題
  • 接口可繼承接口(extends),構建接口層級
  • 常量接口模式(如 Months)替代 enum(Java 5 前)

8. 內部類:封裝與回調利器

  • 成員內部類:可 private/protected,完全隱藏實現
  • 方法/作用域內部類:實現細節不外洩
  • 匿名內部類:new Interface() { ... } 就地實現回調/策略
  • 鏈接外部類:內部類實例持有外部類引用(Outer.this),可訪問所有成員(含 private)
  • static 內部類:無外部引用,可獨立創建,常用作測試床

9. 控制框架實戰:溫室自動化

  • Event 抽象基類:ready()、action()、description()
  • Controller 管理 EventSet,run() 輪詢就緒事件執行 action()
  • 具體事件(LightOn/WaterOff/Bell/Restart)作為 private 內部類,訪問外部狀態(light/water/thermostat)零阻力
  • 完美演示「內部類 = 多重繼承的替代方案」

10. 構建器與多態

  • 調用順序:基類構建器 → 成員初始化 → 導出類構建器主體
  • 構建器中調用動態綁定方法危險:導出類字段尚未初始化(仍為 0/null),如 Glyph → RoundGlyph.draw() 讀到 radius=0
  • 規則:構建器只調用 final/private/static 方法

11. 設計原則:組合優於繼承、區分「是一個」與「類似於」

  • 純繼承 = 「是一個」,接口完全一致,完美替換
  • 擴展接口 = 「類似於」,新增方法需向下轉型(RTTI/instanceof)調用
  • 策略模式例:Stage 持有 Actor 接口,運行期動態換裝 HappyActor/SadActor,比繼承更靈活
  • RTTI:((MoreUseful)obj).u() 運行期檢查,失敗拋 ClassCastException

12. 總結

多態非孤立特性,需配合抽象、繼承、動態綁定。核心價值:將變化的事物與不變的事物分離,擁抱變化,構建可擴展系統。掌握類之間的協作關系,而非孤立看待單個類,才是 OOP 精髓所在。

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