多態性(C#)
在面向對象編程中繼承性和多態性是重要機制,前面我為大家分享了我對“類的繼承”的理解,哪麼今天我就跟大家分享下我對“多態性(C#)”的理解。
首先我們先來看看多態的定義,同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。
C#中多態分為兩種形式,一種是編譯的多態,一種是運行的多態;而所涉及到多態的有重載、重寫、虛方法、抽象方法和隱藏方法。
下面來看看這一段代碼,我們從代碼中來分析他們的概念及區別:
public abstract class A
{
public abstract void prind();
}
public class B:A
{
public override void prind()
{
Console.WriteLine("我是B類,我重寫了A類的抽象方法prind()");
}
public virtual void Bprind()
{
Console.WriteLine("我是B類中的虛方法,我可以被繼承B類的派生類重寫");
}
public void Nprind()
{
Console.WriteLine("Nprind");
}
}
public class C:B
{
public override Bprind()
{
Console.WriteLine("我重寫了B類的虛方法Bprind");
}
new public void Nprind()
{
Console.WriteLine("我是隱藏Nprind");
}
/* 下面是另一種隱藏方法的表現形式
public new void Nprind()
{
Console.WriteLine("我是隱藏Nprind");
}
*/
public void Cprind()
{
Console.WriteLine("我是Cprind方法");
}
public void Cprind(string str)
{
Console.WriteLine(str+"我被重載了");
}
}
class D
{
static void Main(string []arge)
{
B b=new B();
B bc=new C();
C c=new C();
//重寫抽象方法
b.prind();
//重寫虛方法
b.Bprind();
bc.Bprind();
//隱藏方法
b.Nprind();
bc.Nprind();
c.Nprind();
//重載
bc.Cprind();
bc.Cprind("E");
Console.Read();
}
}
輸出結果:
我是B類,我重寫了A類的抽象方法prind()
我是B類中的虛方法,我可以被繼承B類的派生類重寫
我重寫了B類的虛方法Bprind
Nprind
Nprind
我是隱藏Nprind
我是Cprind方法
E我被重載了
如果單看這段代碼可能會看的很費力,所以我們來聽聽類他們之間的對話。
D:A類因為你是抽象類,所以你可以定義抽象方法,定義的抽象方法prind可以被繼承你的子類重寫;因此B類可以重寫你的抽象方法prind。
A:我可以被繼承我的子類B重寫,哪麼我也可以被其他的子類重寫咯,也就是說我使用了多態性。
D:是的你使用了多態性中涉及的抽象方法,因為你的所有子類都可以對你的抽象方法重寫,所以你符合了多態性的定義;但你的所有子類都要注意,重寫你的抽象方法必須要用到override關鍵字、修飾符要相同、傳遞的參數個數和類型也都要一樣及方法的返回值都要一樣。
D:B類你自身的Bprind方法是虛方法也可以被繼承你的子類重寫,不過你和A類不同的是,你自身也可以調用這個虛方法。
B:為什麼Bprind會是虛方法呢?它和別的方法也沒什麼不同啊,只是多了個virtual關鍵字而已,難道加了virtual關鍵字的就是虛方法?
D:對的,虛方法就是必須要加上virtual關鍵字,而沒有加virtual或別的關鍵字的我們叫它為非虛方法;也是因為是虛方法才可以重寫,非虛方法是不能重寫的;但要注意只有繼承你的子類才可以重寫你的虛方法。
B:哦,所以C類可以重寫我的Bprind這個虛方法。
D:C類你不但重寫了父類B的虛方法,還把B類中的Nprind方法寫在了隱藏方法了,而已還對自身的Cprind方法進行了重載。
C:聽到你跟A、B類的對話我知道了我是重寫了虛方法,但這個隱藏方法和重載了Cprind方法,又是什麼回事呢?
D:隱藏方法和重寫方法差不多,只是關鍵字不是override,而改成了new;還有不同的是new可以在修飾符前或後。而重載是在同一個作用域中使用了相同的方法名,修飾符、返回值、參數都可以不相同。
C:隱藏方法我自己能調用吧,但如果實例化父類時引用的是我,哪麼調用的應該是我的還是父類的方法呢?
D:隱藏方法你自己可以,但只有是對你自己實例時調用的才是你,而如果父類實例時引用的是你,哪麼調用的將是父類的方法。
首先我們先從他們對話和給合代碼來看看,重載與重寫的區別:
重載: 重寫:
修飾符 可以不同 必須相同
參數個數及類型 可以不同 必須相同
返回值 可以不同 必須相同
方法名 必須相同 必須相同
接下來我們來看看抽象方法、隱藏方法、虛方法的注意事項:
抽象方法:
1.在基類中定義,派生類中重寫。
2.抽象方法只有在抽象類中才可使用。
3.抽象類不能實例化。
4.必須使用abstract。
隱藏方法:
1.派生類中定義的和基類中的某個方法名相同。
2.父類調用父類的方法,而子類調用子類的方法。
3.使用new關鍵字,虛方法也能使用。
虛方法:
1.在父類中定義的,子類可以重寫。
2.使用virtual關鍵字。
注:父類自身也可調用。