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

Effective C# 原則 20:辨析介面實作與虛擬函式覆寫的本質差異

     編輯:關於C#

表象相似,實則迥異

乍看之下,介面實作與虛擬函式覆寫都讓衍生類別提供具體實作。但兩者語意、繫結機制、版本演進規則完全不同。

介面方法非虛擬:靜態繫結與隱藏機制

interface IMsg { void Message(); }
public class MyClass : IMsg {
    public void Message() => Console.WriteLine("MyClass");
}
public class MyDerivedClass : MyClass {
    public new void Message() => Console.WriteLine("MyDerivedClass"); // 隱藏,非覆寫
}

透過 IMsg 參考呼叫 Message() 時,永遠繫結至實作該介面的具體類別,不受衍生關係影響:

MyDerivedClass d = new MyDerivedClass();
d.Message();           // "MyDerivedClass"
((IMsg)d).Message();   // "MyClass" —— 介面繫結至 MyClass 實作!
((MyClass)d).Message(); // "MyClass"

讓介面行為可覆寫:兩種途徑

  1. 衍生類別重新實作介面(class MyDerived : MyClass, IMsg),但需加 new 隱藏基類實作,基類參考仍呼叫舊版本。
  2. 基類將方法標記為 virtual(推薦):
public class MyClass : IMsg {
    public virtual void Message() => Console.WriteLine("MyClass");
}
public class MyDerivedClass : MyClass {
    public override void Message() => Console.WriteLine("MyDerivedClass");
}
// 現在所有管道(衍生類別參考、基類參考、介面參考)皆呼叫覆寫版本

抽象方法實作介面:強制衍生類別實作

public abstract class MyClass : IMsg {
    public abstract void Message(); // 介面方法以抽象方法實作
}

所有衍生類別必須覆寫實作,介面契約內建於類別階層中。

隱性介面實作:限制存取管道

public struct Customer : IComparable {
    int IComparable.CompareTo(object obj) { ... } // 僅透過 IComparable 存取
    public int CompareTo(Customer other) { ... }  // 型別安全公開版本
}

消費者無法直接呼叫 非型別安全版本,必須強制轉型為介面,配合原則 26 型別安全多載模式完美運作。

核心差異總結

特性介面實作虛擬函式覆寫
繫結時機編譯期(依實作類別)執行期(依物件型別)
衍生類別修改行為需重新實作介面或基類改 virtual直接 override
版本演進介面一旦發布不可變可新增 virtual 成員
多重實作支援顯性實作解決衝突單一繼承鏈

設計指引

  • 介面定義契約(What),虛擬函式定義可變更行為(How)。
  • 預期衍生類別需修改行為 → 設計為 virtual。
  • 需隱藏實作細節/提供多種實作 → 使用隱性介面實作。
  • 介面方法預設非虛擬,切勿誤以為具備多型行為。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved