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

C# 介面 vs 抽象類別:繼承機制核心差異、適用場景與設計決策指南

     編輯:關於C語言

一、 核心定義對比

特性介面抽象類別
關鍵字interfaceabstract class
成員類型方法、屬性、事件、索引子 (皆隱含 public abstract)任意成員 (欄位、建構函式、非抽象方法、私有成員等)
實作不可包含實作 (C# 8.0 前) / 可含預設實作 (C# 8.0+)可包含完整實作與共享邏輯
繼承限制類別可實作多個介面類別單一繼承
建構函式無可有 (供衍生類別呼叫)
存取修飾詞成員預設 public,不可為 private/protected (C# 8.0 前)支援完整存取修飾詞
版本演進修改介面 = 破壞所有實作類別 (C# 8.0 前)新增非抽象成員 = 不破壞衍生類別

二、 介面優勢:契約、多型、解耦

// 契約定義
public interface IAnimal {
    int EyeCount { get; }
    void MakeSound(); // 強制實作,命名統一
}

// 實作
public class Dog : IAnimal {
    public int EyeCount => 2;
    public void MakeSound() => Console.WriteLine("Woof!");
}
public class Cat : IAnimal {
    public int EyeCount => 2;
    public void MakeSound() => Console.WriteLine("Meow~");
}

// 多型使用:介面型別參數
public void Feed(IAnimal animal) {
    Console.WriteLine($"Feeding {animal.GetType().Name}");
    animal.MakeSound(); // 動態派發,Dog/Cat 行為不同
}

// 新增類別零修改既有代碼
public class Duck : IAnimal { ... } // 直接串接
  • 命名規範:介面強制統一方法簽名,避免 Bark()/Woof()/MakeNoise() 混亂。
  • 多實作替換:依賴介面而非具體類別 (DIP),測試易 Mock、插件架構鬆耦合。
  • 菱形繼承解決:C# 無多重繼承,介面完美解決「類別需具備多種能力」需求。

三、 抽象類別優勢:代碼復用、封裝、版本穩定

public abstract class AnimalBase {
    // 共享欄位/邏輯
    protected int _legs = 4;
    public int Legs => _legs;

    // 共享實作 (封裝)
    public void Sleep() => Console.WriteLine("Zzz...");

    // 模板方法模式
    public void DailyRoutine() {
        WakeUp();
        Eat();      // 抽象,強制子類實作
        Play();
        Sleep();
    }
    protected abstract void Eat();
    protected virtual void WakeUp() => Console.WriteLine("Wake up");
    protected virtual void Play() => Console.WriteLine("Playing");
}

public class Dog : AnimalBase {
    protected override void Eat() => Console.WriteLine("Eating bone");
}
  • 代碼復用:共享欄位、預設實作、模板方法,避免重複代碼。
  • 封裝內部邏輯:DailyRoutine() 定義演算法骨架,子類只填細節。
  • 演進友善:新增 virtual 方法不破壞既有衍生類別;介面新增成員 (無預設實作) 則強制所有實作類別修改。
  • Provider 模式:ASP.NET Provider、Entity Framework 皆用抽象類別而非介面,因需豐富共享基礎設施。

四、 決策流程圖 (文字版)

  1. 是否需要多重實作 (類別已繼承其他基類)? → 介面。
  2. 是否有大量共享代碼/狀態 需復用? → 抽象類別。
  3. 是否定義「是一種」關係 (is-a,核心領域模型)? → 抽象類別。
  4. 是否定義「能做什麼」能力 (can-do,橫切關注點)? → 介面 (如 IDisposable, IComparable, ISerializable)。
  5. 是否需版本演進穩定 (公開 API 庫)? → 傾向抽象類別 或 C# 8.0+ interface 預設實作。

五、 綜合實戰:兩者結合

// 1. 介面定義契約
public interface IRepository {
    T GetById(int id);
    void Save(T entity);
}

// 2. 抽象類別提供共享基礎設施 (連線管理、日誌、事務)
public abstract class RepositoryBase : IRepository {
    protected readonly IDbConnection _conn;
    protected RepositoryBase(IDbConnection conn) => _conn = conn;
    public abstract T GetById(int id);
    public abstract void Save(T entity);
    protected void Log(string msg) => /* 共享日誌 */;
}

// 3. 具體實作
public class SqlUserRepository : RepositoryBase {
    public SqlUserRepository(IDbConnection conn) : base(conn) {}
    public override User GetById(int id) => /* SQL 查詢 */;
    public override void Save(User u) => /* SQL 存儲 */;
}

六、 總結

介面 = 契約 + 多型 + 解耦 + 多重實作。抽象類別 = 代碼復用 + 封裝 + 模板方法 + 版本穩定。現代 C# 開發常見模式:介面定義 API 邊界,抽象類別提供骨幹實作,具體類別繼承抽象類別並實作介面。單一繼承限制下,善用介面組合能力,抽象類別共享邏輯,是優雅物件導向設計的關鍵。

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