C#易錯易混淆知識總結(七)--{多型}{抽象類於抽象方法}
一 多型
里氏替換原則就已經說明了多型的精髓“子類物件可以替換父類物件的位置,而程式的功能不受影響”。
class Person { //定義虛方法以備子類重寫,當子類替換父類物件的位置時,可以表現出多型 public virtual void Run() { Console.WriteLine("我是人,我會跑!"); } public virtual void Say() { Console.WriteLine("我是人,我會說話!"); } }
//定義Teacher類繼承Person
class Teacher:Person
{
public override void Run()
{
Console.WriteLine("我是老師,我必須慢速跑");
}
public override void Say()
{
Console.WriteLine("我是老師,我得說表揚的話!");
}
}
//定義Student類繼承Person
class Student : Person
{
//子類重寫了父類的虛方法
public override void Run()
{
Console.WriteLine("我是學生,我會加速跑!");
}
public override void Say()
{
Console.WriteLine("我是學生,我會說英語!");
}
}
//實現多型的類
class FeatureHuman
{
/// <summary>
/// 這個方法就提現了多型,當傳入的是子類的物件的時候,p指向的是子類物件,就可以呼叫子類重寫父類方法後的方法
/// </summary>
/// <param name="p">父類或者子類物件</param>
public void OutPutFeature(Person p)
{
p.Run();
p.Say();
}
}
主體程式碼和實現多型的方法如下:
static void Main(string[] args) { FeatureHuman fea = new FeatureHuman(); //人的特點 Person p = new Person(); Program pro = new Program(); fea.OutPutFeature(p); //學生的特點 Student s = new Student(); fea.OutPutFeature(s); //老師的特點 Teacher t = new Teacher(); fea.OutPutFeature(t); Console.ReadKey(); }
執行,列印結果如下:
這裡可以發現,我們outputFeature方法根據傳入的實體物件不同(父類變數指向了子類的物件),而打印出了不同人物的特點,這就是多型。
多型總結如下:
二,抽象類和抽象方法
在C#中使用abstract關鍵字修飾的類和方法,叫做抽象類和抽象方法。
1)抽象類中可以擁有沒抽象成員,為了繼承給他的子類呼叫 (抽象類就是為了定義抽象成員,繼承給子類去實現,同時子類也可以呼叫父類的非抽象成員)
abstract class Person { //private int nAge; //abstract string strName; //抽象類可以包含不抽象的成員,可以給繼承的子類使用 public void Say() { Console.WriteLine("我是父類,我是人!"); } public virtual void Sing() { Console.WriteLine("我是父類,我是人,我可以唱歌!"); } //Run的抽象方法 public abstract void Run(); }
2)抽象類中可以有virtual修飾的虛方法
如上面的程式碼,在抽象類中定義了virtual修飾的方法,編譯通過。抽象類就是為了定義抽象成員,繼承給子類去實現,所以子類也可以實現抽象類中的虛方法。
3)抽象類不能例項化,因為有抽象成員,而抽象成員沒有方法體,如下圖,
4)抽象成員不能私有,如果私有子類沒有辦法訪問
我們可以在抽象類中定義私有成員,但是沒有意義。因為子類根本訪問不到這些私有成員,而抽象類本身也不能例項化,所以私有成員訪問不到。
5)子類必須重寫父類的抽象方法
在上面程式碼的基礎上,我們定義一個Student類,繼承抽象類,但是不實現抽象類的抽象方法,編譯報錯。程式碼如下:
6)在子類中沒有辦法通過base關鍵字呼叫父類抽象方法
原理同上,抽象類的抽象發放沒有實現語句,就算呼叫也沒有意義。但是可以使用base關鍵字呼叫非抽象方法,程式碼如下:
class Program { static void Main(string[] args) { //Person p = new Person(); Student s = new Student(); s.Run(); Console.ReadLine(); } } class Student : Person { public override void Run() { base.Say(); Console.WriteLine("我是學生,繼承了父類,我可以跑!"); } }
總結如下:
抽象方法:
1)抽象方法必須定義在抽象類中,
2)抽象方法必須使用關鍵字修飾,示例程式碼如下:
abstract class Person { //private int nAge; //abstract string strName; //抽象類可以包含不抽象的成員,可以給繼承的子類使用 public void Say() { Console.WriteLine("我是父類,我是人!"); } public virtual void Sing() { Console.WriteLine("我是父類,我是人,我可以唱歌!"); } //Run的抽象方法,不能有方法體,留給子類實現 public abstract void Run();
那麼什麼時候使用抽象類呢?
①子類必須重寫父類的方法(相當於定義了一個標準,規範)
②父類沒有必要例項化,就用抽象類
③抽象類是為了繼承,為了多型