MSDN---类的多态

透過繼承,類別可以當做多種型別使用,包括可以用來當做本身的型別、任何基底型別,或實作介面的任何介面型別。這稱為多型。在 C# 中,每種型別都是多型的。型別可以用來當做本身的型別或 Object 執行個體,因為任何型別都會自動將 Object 視為基底型別。

多型不但對衍生類別來說很重要,對於基底類別也十分重要。事實上,只要使用基底類別,就可以使用已轉換成基底類別型別的衍生類別物件。基底類別的設計人員可以預期在衍生型別中,基底類別的各方面有可能會改變。例如,假設有一個基底類別為汽車,那麼其所包含的行為就可能視汽車是休旅車或敞篷車而有不同。基底類別可以將這些類別成員標示成虛擬,讓代表敞篷車和休旅車的衍生類別覆寫該行為。

如需詳細資訊,請參閱繼承。

多型概觀
當衍生類別繼承自基底類別時,就會取得基底類別的所有方法、欄位、屬性和事件。若要變更基底類別的資料和行為,可以使用兩種方法:您可以用新的衍生成員取代基底成員,或覆寫虛擬基底成員。

用新的衍生成員取代基底類別的成員時,需要使用 new 關鍵字。如果基底類別定義了方法、欄位或屬性,就會使用 new 關鍵字在衍生類別上建立該方法、欄位或屬性的新定義。new 關鍵字會放在要取代之類別成員的傳回型別前。例如:

C#  複製程式碼
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 關鍵字時,會呼叫新的類別成員,而不是已被取代的基底類別成員。這些基底類別成員稱為隱藏成員。您還是可以呼叫隱藏類別成員,只要將衍生類別的執行個體轉換成基底類別的執行個體即可。例如:

C#  複製程式碼
DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

 

若要以衍生類別的執行個體完全取代基底類別的類別成員,基底類別必須將該成員宣告為虛擬。只要在成員的傳回型別前面加上 virtual 關鍵字即可。接下來衍生類別就可以使用 override 關鍵字 (而非 new),以其本身的類別實作取代基底類別實作。例如:

C#  複製程式碼
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; }
    }
}

 

欄位不能是虛擬的,只有方法、屬性、事件和索引子可以是虛擬的。當衍生類別覆寫虛擬成員時,即使該類別的執行個體是當做基底類別的執行個體存取時,也會呼叫該成員。例如:

C#  複製程式碼
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 宣告覆寫該成員與否,都可以覆寫該成員。例如:

C#  複製程式碼
public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

 
C#  複製程式碼
public class C : B
{
    public override void DoWork() { }
}

 

衍生類別可以將覆寫宣告為密封,停止虛擬繼承。這必須在類別成員宣告中,將 sealed 關鍵字放在 override 關鍵字前面。例如:

C#  複製程式碼
public class C : B
{
    public sealed override void DoWork() { }
}

 

在上面的範例中,方法 DoWork 對衍生自 C 的任何類別來說,就不再是虛擬的,但對 C 的執行個體來說,即使轉換成型別 B 或型別 A,該方法還是虛擬的。您可以使用 new 關鍵字,用衍生類別取代密封方法,如下列範例所示:

C#  複製程式碼
public class D : C
{
    public new void DoWork() { }
}

 

在上面的範例中,如果使用型別 D 的變數在 D 上呼叫 DoWork,就會呼叫新的 DoWork。如果使用型別 C、B 或 A 的變數來存取 D 的執行個體,DoWork 呼叫就會照著虛擬繼承的規則,將呼叫傳送至類別 C 上的 DoWork 實作。

取代或覆寫方法或屬性的衍生類別,仍可使用 base 關鍵字來存取基底類別的方法或屬性。例如:

C#  複製程式碼
public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

 
C#  複製程式碼
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。

注意事項
虛擬成員最好能在其實作中使用 base 呼叫該成員的基底類別實作。使用基底類別行為可讓衍生類別只需實作其特有的行為。如果不呼叫基底類別實作,衍生類別與基底類別的行為相容與否,就要視衍生類別而定。
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值