[你必須知道的.NET]第十七回:貌合神離:覆寫和重載
博客園CLR基礎研究團隊|CLR團隊精品系列|Anytao技術博客
[你必須知道的.NET]第十七回:貌合神離:覆寫和重載
發布日期:2007.11.7 作者:Anytao
? 2007 Anytao.com ,原創作品,轉貼請注明作者和出處。
本文將介紹以下內容:
- 什么是覆寫,什么是重載
- 覆寫與重載的區別
- 覆寫與重載在多態特性中的應用
1. 引言
覆寫(override)與重載(overload),是成就.NET面向對象多態特性的基本技術之一,兩個貌似相似而實則不然的概念,常常帶給我們很多的誤解,因此有必要以專題來討論清楚其區別,而更重要的是關注其在多態中的應用。
在系列中,我們先后都有關于這一話題的點滴論述,本文以專題的形式再次做以深度討論,相關的內容請對前文做以參考。
2. 認識覆寫和重載
從一個示例開始來認識什么是覆寫,什么是重載?
{
//定義虛方法
public virtual void MyFunc()
{
}
//參數列表不同,virtual不足以區分
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、abstrcat和override修飾。
概念:抽象方法
抽象方法就是以abstract關鍵字修飾的方法,抽象方法可以看作是沒有實現體的虛方法,并且必須在派生類中被覆寫,如果一個類包括抽象方法,則該類就是一個抽象類。因此,抽象方法其實隱含為虛方法,只是在聲明和調用語法上有所不同。abstract和virtual一起使用是錯誤的。
2.2 重載基礎篇
重載,就是在同一個類中存在多個同名的方法,而這些方法的參數列表和返回值類型不同。值得注意的是,重載的概念并非面向對象編程的范疇,從編譯器角度理解,不同的參數列表、不同的返回值類型,就意味著不同的方法名。也就是說,方法的地址,在編譯期就已經確定,是這一種靜態綁定。從示例中,我們總結重載的基本特征包括:
- 重載存在于同一個類中。
- 重載方法要求具有相同的方法名,不同的參數列表,返回值類型可以相同也可以不同(通過operator implicit 可以實現一定程度的返回值重載,不過不值得推薦)。
- .NET 2.0引入泛型技術,使得相同的參數列表、相同的返回值類型的情況也可以構成重載。
3. 在多態中的應用
多態性,簡單的說就是“一個接口,多個方法”,具體表現為相同的方法簽名代表不同的方法實現,同一操作作用于不同的對象,產生不同的執行結果。在.NET中,覆寫實現了運行時的多態性,而重載實現了編譯時的多態性。
運行時的多態性,又稱為動態聯編,通過虛方法的動態調度,在運行時根據實際的調用實例類型決定調用的方法實現,從而產生不同的執行結果。
{
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);
}
public static void Main()
{
Base B = new Base();
B.MyFunc("Hello");
Derived A = new Derived();
B = A;
B.MyFunc("Morning");
}
}
從結果中可知,對象B兩次執行B.MyFunc調用了不同的方法,第一次調用基類方法MyFunc,而第二次調用了派生類方法MyFunc。在執行過程中,對象B先后指向了不同的類的實例,從而動態調用了不同的實例方法,顯然這一執行操作并非確定于編譯時,而是在運行時根據對象B執行的不同類型來確定的。我們在此不分析虛擬方法的動態調度機制,而只關注通過虛方法覆寫而實現的多態特性,詳細的實現機制請參考本系列的其它內容。
編譯時的多態性,又稱為靜態聯編,一般包括方法重載和運算符重載。對于非虛方法來說,在編譯時通過方法的參數列表和返回值類型決定不同操作,實現編譯時的多態性。例如,在實際的開發過程中,.NET開發工具Visual Studio的智能感知功能就很好的為方法重載提供了很好的交互手段,例如:
從智能感知中可知方法MyFunc在派生類Derived中有三次重載,調用哪種方法由程序開發者根據其參數、返回值的不同而決定。由此可見,方法重載是一種編譯時的多態,對象A調用哪種方法在編譯時就已經確定。
4. 比較,還是規則
- 如果基訪問引用的是一個抽象方法,則將導致編譯錯誤。
{
public abstract void Func();
}
class Derived: Base
{
//覆寫基類抽象方法
public override void Func()
{
base.Func();
}
}
- 虛方法不能是靜態的、密封的。
- 覆寫實現的多態確定于運行時,因此更加的靈活和抽象;重載實現的多態確定于編譯時,因此更加的簡單和高效。二者各有特點與應用,不可替代。
在下表中,將覆寫與重載做以總結性的對比,主要包括:
|
規則 |
覆寫(override) |
重載(overload) |
|
存在位置 |
存在于有繼承關系的不同類中 |
存在于同一個類中 |
|
調用機制 |
運行時確定 |
編譯時確定 |
|
方法名 |
必須相同 |
必須相同 |
|
參數列表 |
必須相同 |
必須不同 |
|
返回值類型 |
必須相同 |
可以不相同 |
|
泛型方法 |
可以覆寫 |
可以重載 |
注:參數列表相同表示參數的個數相同,并且相同位置的參數類型也相同。
5. 結論
深入的理解覆寫和重載,是對多態特性和面向對象機制的有力補充,本文從基本概念到應用領域將兩個概念進行一一梳理,通過對比整理區別,還覆寫和重載以更全面的認知角度,同時也更能從側面深入的了解運行時多態與編譯時多態的不同情況。
參考文獻
(web)TerryLee, 再談重載與覆寫,http://www.rzrgm.cn/Terrylee/archive/2006/03/10/347104.html
(web)失落的BLOGS,C#泛型,http://www.rzrgm.cn/lianyonglove/archive/2007/07/27/720682.html
溫故知新
[開篇有益]
[第一回:恩怨情仇:is和as]
[第二回:對抽象編程:接口和抽象類]
[第三回:歷史糾葛:特性和屬性]
[第四回:后來居上:class和struct]
[第五回:深入淺出關鍵字---把new說透]
[第六回:深入淺出關鍵字---base和this]
[第七回:品味類型---從通用類型系統開始]
[第八回:品味類型---值類型與引用類型(上)-內存有理]
[第九回:品味類型---值類型與引用類型(中)-規則無邊]
[第十回:品味類型---值類型與引用類型(下)-應用征途]
[第十一回:參數之惑---傳遞的藝術(上)]
[第十二回:參數之惑---傳遞的藝術(下)]
[第十三回:從Hello, world開始認識IL]
[第十四回:認識IL代碼---從開始到現在]
[第十五回:繼承本質論]
[第十六回:深入淺出關鍵字---using全接觸]
? 2007 Anytao.com
原創作品,轉貼請注明作者和出處,留此信息。
本文以“現狀”提供且沒有任何擔保,同時也沒有授予任何權利。
This posting is provided "AS IS" with no warranties, and confers no rights.
Worktile,新一代簡單好用、體驗極致的團隊協同、項目管理工具,讓你和你的團隊隨時隨地一起工作。完全免費,現在就去了解一下吧。
https://worktile.com



浙公網安備 33010602011771號