[C#] 多形

摘要:[C#] 多形

文章轉自

http://msdn.microsoft.com/zh-tw/library/ms173152%28v=VS.80%29.aspx

C# 程式設計手冊
多型 (C# 程式設計手冊)

透過繼承,類 別可以當做多種型別使用,包括可以用來當做本身的型別、任何基底型別,或實作介面的任何介 面型別。這稱為多型。在 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