一、重載:同一個範圍內發生(比如一個類裡面),定義一系列同名方法,但是方法的參數列表不同。這樣才能通過傳遞不同的參數來決定到底調用哪一個。
值得注意的是,方法重載只有通過參數不同來判斷調用哪個方法,而不能通過傳回值。至於原因,可以這樣理解,你調用一個方法,如果有多個方法同名,系統必須要知道到底你要調用哪一個,參數可以協助系統在方法入口處得到答案,他根據你給的參數就知道該使用哪個方法。如果只有傳回值的不同,很多情況系統是不可能得到有效判斷條件的,比如:double method();int method();如果你這樣調用:method()。系統當然不知道該調用哪個。
樣本:
//傳回值相同,參數不同
class BillPayment { void PayBill(int TelephoneNumber) { //此方法用於支付固定電話費 } void PayBill(long CustomerNumber) { //此方法用於支付電費 } void PayBill(long CustomerNumber,double amount) { //次方法用於支付行動電話費 } }}
//傳回值相同,參數個數不同
class Add{ int addtion(int num1,int num2) { return num1+num2; } int addtion(int num1,int num2,int num3) { returnnum1+num2+num3; }}
//參數不同,傳回值不同
int Method(int[] numbers){}double Method(double[] numbers){}
註:泛型出現後,相同參數,相同傳回值的方法也能構成重載,這裡不介紹。
二、重寫:繼承時發生,在子類中重新定義父類中的方法,子類中的方法和父類的方法是一樣的,即方法名,參數,傳回值都相同。
例如:基類方法聲明為virtual(虛方法),衍生類別中使用override申明此方法的重寫.
重寫override一般用於介面實現和繼承類的方法改寫,要注意:
1、覆蓋的方法的標誌必須要和被覆蓋的方法的名字和參數完全符合,才能達到覆蓋的效果;
2、覆蓋的方法的傳回值必須和被覆蓋的方法的返回一致;
3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。
樣本:
namespace 方法重寫{ class Program { static voidMain(string[] args) { BaseClass CO =new ClassOverride(); CO.SetName("Override"); }//基類 public classBaseClass { public virtualvoid SetName(string name) { Console.WriteLine("基類:我的名字是" + name); } } //衍生類別 public classClassOverride : BaseClass { publicoverride void SetName(string name) { Console.WriteLine("Override:我的名字是" + name); } } }}
在方法重寫中,我們介紹了虛方法,那麼虛方法和抽象方法有什麼區別呢?
1.虛方法有一個實現部分可以被子類繼承,從而使子類獲得和基類相同的方法,另外也為衍生類別提供了覆蓋該方法的選項。相反,抽象方法沒有提供實現部分,是一種強制衍生類別覆蓋的方法(否則衍生類別不能成具體類)
2.(abstract)抽象方法只能在抽象類別中聲明,(virtual)虛方法不是。
3.(abstract)抽象方法必須在衍生類別中重寫而(virtual)虛方法不必。
4.(abstract)抽象方法不能聲明方法實體,虛方法可以。
個人感覺,方法重載和方法重寫都有點像多態,同一個方法的多種形態:執行“相同”的方法,卻通過它們自己的實現代碼來實現,即同一種方法,不同的對象會產生不同的結果。
三、隱藏(方法):基類方法不做申明(預設為非虛方法),在衍生類別中使用new聲明此方法的隱藏。隱藏時,訪問父類則調用父類的方法,訪問子類則調用子類的方法。
樣本:
namespace 隱藏{ class Program { static voidMain(string[] args) { ClassNew CN =new ClassNew(); CN.SetName("new"); BaseClass BC =CN; BC.SetName("基類"); } //基類 public classBaseClass { public voidSetName(string name) { Console.WriteLine("基類:我的名字是" + name); } }//衍生類別 public classClassNew : BaseClass { //這裡如果不使用new,將產生警告! new publicvoid SetName(string name) { Console.WriteLine("new:我的名字是" + name); } } }}
運行結果:new:我的名字是new
基類:我的名字是基類
如果上述扔不好理解,我們再舉一個隱藏靜態變數的例子
namespace 隱藏繼承成員{ class Program { public classBaseClass { public static int A = 123; } public classClassNew : BaseClass { new public static int A = 456; static voidMain(string[] args) { Console.WriteLine(A); } } }}
運行結果:456
註:不僅有方法隱藏,還有其他的,通過繼承隱藏名稱一般採用下列形式之一:
1.引入類或結構中的常數、指定、屬性或類型隱藏具有相同名稱的所有基類成員。
2.引入類或結構中的方法隱藏基類中具有相同名稱的屬性、欄位和類型。同時也隱藏具有相同簽名的所有基類方法。
3.引入類或結構中的索引器將隱藏具有相同名稱的所有基類索引器。
4.在同一成員上同時使用 new 和 override 是錯誤的。
另外,在不隱藏繼承成員的聲明中使用 new 修飾符將產生警告。在隱藏繼承成員的生命中不使用new修飾符也將產生警告