摘要:[C#] 多形
文章轉自
http://msdn.microsoft.com/zh-tw/library/ms173152%28v=VS.80%29.aspx
透過繼承,類 別可以當做多種型別使用,包括可以用來當做本身的型別、任何基底型別,或實作介面的任何介 面型別。這稱為多型。在 C# 中,每種型別都是多型的。型別可以用來當做本身的型別或 Object 執行個體,因為任何型別都會自動將 Object 視為基底型別。
多型不但對衍生類別來說很重要,對於基底類別也十分重 要。事實上,只要使用基 底類別,就可以使用已轉換成基底類別型別的衍生類別物件。基底類別的設計人員可以預期在衍生型別中,基底類別的各方面有可能會改變。例如,假設有 一個基底類別為汽車,那麼其所包含的行為就可能視汽車是休旅車或敞篷車而有不同。基底類別可以將這些類別成員標示成虛擬,讓代表敞篷車和休旅車的衍生類別 覆寫該行為。
如需詳細資訊,請參閱繼 承。
多型概觀
當衍生類別繼承自基底類別時,就會取得基底類別的所有方法、欄位、屬性和事件。若 要變更基底類別的資料和行為,可以使用兩種方法:您可以用新的衍生成員取代基底成員,或覆寫虛擬基底成員。
用新的衍生成員取代基底類別的成 員時,需要使用 new 關鍵字。如果基底類別定義了方法、欄位或屬性,就會使用 new 關鍵字在衍生類別上建立該方法、欄位或屬性的新定義。new 關鍵字會放在要取代之類別成員的傳回型別前。例如:
public class BaseClass { public void DoWork() { } public int WorkField; public int WorkProperty { get { return 0; } } } public class DerivedClass : BaseClass { public new void DoWork() { } public new int WorkField; public new int WorkProperty { get { return 0; } } }
使用 new 關鍵字時,會呼叫新的類別成員,而不是已被取代的基底類別成員。這些基底類別成員稱為隱藏成員。您還是可以呼叫隱藏類別成員,只要將衍生類別的執行個體轉 換成基底類別的執行個體即可。例如:
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Calls the old method.
若要以衍生類別的執行個體完全取代基底類別的類別成員,基底類別必須將該成員宣告為 虛擬。只要在成員的傳回型別前面加上 virtual 關鍵字即可。接下來衍生類別就可以使用 override 關鍵字 (而非 new),以其本身的類別實作取代基底類別實作。例如:
public class BaseClass { public virtual void DoWork() { } public virtual int WorkProperty { get { return 0; } } } public class DerivedClass : BaseClass { public override void DoWork() { } public override int WorkProperty { get { return 0; } } }
欄位不能是虛擬的,只有方法、屬性、事件和索引子可以是虛擬的。當衍生類別覆寫虛擬 成員時,即使該類別的執行個體是當做基底類別的執行個體存取時,也會呼叫該成員。例如:
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Also calls the new method.
虛擬成員和屬性可讓您預先計劃,以因應未來可能的擴充。由於無論呼叫端使用的型別為 何,都會呼叫虛擬成員,使衍生類別可以完全改變基底類別的主要行為。
虛擬成員會永遠保持虛擬的狀態,無論原本宣告虛擬成員的類別之後又宣告 了多少類別。如果類別 A 宣告了虛擬成員,而類別 B 衍生自 A,類別 C 又衍生自 B,則類別 C 會繼承該虛擬成員,而且無論類別 B 宣告覆寫該成員與否,都可以覆寫該成員。例如:
public class A { public virtual void DoWork() { } } public class B : A { public override void DoWork() { } }
public class C : B { public override void DoWork() { } }
衍生類別可以將覆寫宣告為密封,停止虛擬繼承。這必須在類別成員宣告中,將 sealed 關鍵字放在 override 關鍵字前面。例如:
public class C : B { public sealed override void DoWork() { } }
在上面的範例中,方法 DoWork 對衍生自 C 的任何類別來說,就不再是虛擬的,但對 C 的執行個體來說,即使轉換成型別 B 或型別 A,該方法還是虛擬的。您可以使用 new 關鍵字,用衍生類別取代密封方法,如下列範例所示:
public class D : C { public new void DoWork() { } }
在上面的範例中,如果使用型別 D 的變數在 D 上呼叫 DoWork,就會呼叫新的 DoWork。如果使用型別 C、B 或 A 的變數來存取 D 的執行個體,DoWork 呼叫就會照著虛擬繼承的規則,將呼叫傳送至類別 C 上的 DoWork 實作。
取代或覆寫方法 或屬性的衍生類別,仍可使用 base 關鍵字來存取基底類別的方法或屬性。例如:
public class A { public virtual void DoWork() { } } public class B : A { public override void DoWork() { } }
public class C : B { public override void DoWork() { // Call DoWork on B to get B's behavior: base.DoWork(); // DoWork behavior specific to C goes here: // ... } }
如需詳細資訊,請參閱 base。