首先感謝園內前輩 anytao.cnblogs.com,他對面向抽象類別與介面程式設計作出較完善總結。下文直接引用其原話。
一、相同點
- 都無法直接實例化,皆可透過繼承實現其抽象方法。
- 都是面向抽象程式設計的技術基礎,實現了諸多設計模式。
二、不同點
- 介面支援多重繼承;抽象類別無法實現多重繼承。
- 介面只能定義抽象規範;抽象類別既可定義規範,也可提供已實作成員。
- 介面是一組行為規範;抽象類別是一個不完整的類別,著重「族」的概念。
- 介面可用於支援回呼;抽象類別無法實現回呼,因為繼承不支援。
- 介面只包含方法、屬性、索引子、事件的簽章,不能定義欄位與包含實作的方法;抽象類別可定義欄位、屬性、包含實作的方法。
- 介面可作用於實質型別與參考型別;抽象類別只能作用於參考型別。例如
Struct 可繼承介面,不能繼承類別。
透過比較,只能說介面與抽象類別各有所長,無優劣之分。實務上視具體情況斟酌,以下經驗或許能給啟示:
三、規則與場合
- 記住面向物件最重要原則:面向介面程式設計。
- 借助介面與抽象類別,23 個設計模式許多思想被巧妙實現,精髓即:面向抽象程式設計。
- 抽象類別主要用於關係密切的物件;介面最適合為不相關的類別提供通用功能。
- 介面著重 CAN-DO 關係;抽象類別偏重 IS-A 關係。
- 介面多定義物件行為;抽象類別多定義物件屬性。
- 介面定義可用 public、protected、internal、private 修飾詞,但幾乎都定義為 public。
- 「介面不變」是重要考量。擴充時應增加新介面,不可更改現有介面。
- 盡量將介面設計成功能單一的功能區塊。如 .NET Framework 的
IDisposable、IComparable、IEquatable、IEnumerable 等皆只包含一個公用方法。
- 介面名稱前綴大寫「I」是約定,請堅持。
- 介面中所有方法預設為 public。
- 預計出現版本問題時,可建立「抽象類別」。例如建立狗、雞、鴨類別,應考慮抽象出動物類別應對未來變化。介面新增成員會強制修改所有衍生類別並重新編譯,版本問題宜用抽象類別實現。
- 從抽象類別衍生的非抽象類別必須實作所有繼承的抽象方法與抽象存取子。
- 抽象類別不能使用
new 關鍵字,也不能被密封,因為無法實例化。
- 抽象方法宣告中不能使用
static 或 virtual 修飾詞。