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

[你必須知道的.NET]第十七回:貌合神離——覆寫與重載

     編輯:關於.NET

本文介紹內容

  • 什麼是覆寫,什麼是重載
  • 覆寫與重載的區別
  • 覆寫與重載在多態特性中的應用

1. 引言

覆寫(override)與重載(overload),是成就 .NET 面向物件多態特性的基本技術。兩個貌似相似實則不同的概念,常帶來誤解,有必要專題討論清楚區別,更關鍵是關注其在多態中的應用。

2. 認識覆寫與重載

從示例開始:

abstract class Base
{
    public virtual void MyFunc() { }
    public virtual void MyFunc(string str) { }
    public bool MyFunc(string str, int id) { Console.WriteLine("AAA"); return true; }
    public bool MyFunc(int id, string str) { Console.WriteLine("BBB"); return false; }
    public bool MyFunc<T>(string str, int id) { return true; } // 泛型重載
    public abstract void Func();
}

class Derived : Base
{
    public new void MyFunc() { } // 隱藏父類別成員
    public override void MyFunc(string str) { base.MyFunc(str); } // 覆寫基類別成員
    public override void Func() { } // 覆寫抽象方法
}

2.1 覆寫基礎篇

覆寫(重寫):在子類別中重複定義父類別方法,提供不同實現,存在於有繼承關係的父子關係。子類別重寫父類別虛函數後,父類別物件可根據賦予的不同子類別指標動態調用子類別方法。基本特徵:

  • .NET 中只有以 virtual 和 abstract 標記的虛方法與抽象方法才能被直接覆寫。
  • 以關鍵字 override 標記,強調繼承關係中對基類別方法的重寫。
  • 要求相同方法簽名:相同方法名、參數列表、回傳值型別。

虛方法:以 virtual 修飾並在派生類別實現的方法。子類別重寫以 override 標記。虛方法調用在執行時根據調用物件型別決定調用適當覆寫方法。.NET 預設非虛方法。virtual 標記後不可再被 static、abstract、override 修飾。

抽象方法:以 abstract 修飾的方法,可視為無實作體的虛方法,必須在派生類別被覆寫。含抽象方法的類別即為抽象類別。抽象方法隱含為虛方法,聲明與調用語法不同。abstract 與 virtual 同時使用為錯誤。

2.2 重載基礎篇

重載:在同一個類別中存在多個同名方法,參數列表與回傳值型別不同。從編譯器角度,不同參數列表、回傳值型別意味著不同方法名——方法位址在編譯期已確定,屬靜態繫結。基本特徵:

  • 存在於同一個類別中。
  • 相同方法名,不同參數列表,回傳值型別可同可異(透過 operator implicit 可實現一定程度回傳值重載,不推薦)。
  • .NET 2.0 引入泛型,使相同參數列表、相同回傳值型別也可構成重載。

3. 在多態中的應用

多態性:「一個介面,多個方法」。具體表現為相同方法簽名代表不同方法實現,同一操作作用於不同物件產生不同執行結果。在 .NET 中:

  • 覆寫實現執行時多態性(動態繫結)
  • 重載實現編譯時多態性(靜態繫結)

執行時多態性(動態繫結)

透過虛方法動態調度,執行時根據實際調用實例型別決定調用方法實現。

class Base { public virtual void MyFunc(string str) { Console.WriteLine("{0} in Base", str); } }
class Derived : Base { public override void MyFunc(string str) { Console.WriteLine("{0} in Derived", str); } }
static void Main() {
    Base B = new Base(); B.MyFunc("Hello");
    Derived A = new Derived(); B = A; B.MyFunc("Morning");
}

物件 B 兩次呼叫 B.MyFunc 調用不同方法:第一次基類別方法,第二次派生類別方法。執行過程中 B 先後指向不同類別實例,動態調用不同實例方法,並非編譯時確定,而是執行時根據 B 實際型別確定。

編譯時多態性(靜態繫結)

包含方法重載與運算符重載。非虛方法在編譯時透過參數列表與回傳值型別決定不同操作。Visual Studio 智慧感知完美支援方法重載:

物件 A 調用哪種方法在編譯時已確定。

4. 比較,還是規則

  • 若 base 存取的是抽象方法,導致編譯錯誤。
  • 虛方法不能是 static、sealed。
  • 覆寫多態確定於執行時,更靈活抽象;重載多態確定於編譯時,更簡單高效。兩者各有特點與應用,不可替代。

總結對比表

規則覆寫 (override)重載 (overload)
存在位置有繼承關係的不同類別中同一個類別中
調用機制執行時確定編譯時確定
方法名必須相同必須相同
參數列表必須相同必須不同
回傳值型別必須相同可以不相同
泛型方法可以覆寫可以重載

註:參數列表相同 = 參數個數相同,且相同位置參數型別也相同。

5. 結論

深入理解覆寫與重載,是對多態特性與面向物件機制的有力補充。本文從基本概念到應用領域梳理兩概念,透過對比整理區別,還原更全面認知角度,同時側面深入了解執行時多態與編譯時多態的不同情況。

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