淺談C#中的實現繼承

C#中的繼承分爲實現繼承和接口繼承,今天主要談一下實現繼承。

  實現繼承表示一個類型派生於另一個基類型,該類型擁有基類型的所有成員字段和函數。在實現繼承中,派生類型的每個函數採用基類型的實現代碼。——摘自《C#高級編程第六版》92頁

  爲什麼要使用類繼承呢,舉個小例子,假如說我們之前有個類叫Peoplo(人類),他具有身高、體重等屬性,同時還具有喫飯、睡覺等方法,可是由於科技的進步人們又發明了機器人(Robot),它不但可以像人類那樣具有身高、體重,還能夠喫飯、睡覺外,它還具備人類所不具備的功能,例如機器人可以下潛到1000以下的深水中,如果沒有繼承,我們在定義Robot這個類的時候就得重複定義peoplo的成員和Robot所獨特的成員,增加了我們的負擔,使用繼承就可以很好的解決這個問題,如下:

  先看Peoplo類

 

 

 1public class Peoplo
 2{
 3    public int stature getset; }//身高
 4    public int avoirdupois getset; }//體重
 5    public Peoplo()
 6    {
 7        //
 8        //TODO: 在此處添加構造函數邏輯
 9        //
10    }

11    public string dining()//喫飯
12    {
13        return "今天的紅燒肉真好喫!";
14    }

15    public string dreamland()//睡覺
16    {
17        return "爲什麼不是席夢思的牀墊呢?";
18    }

19}

  
  該類定義了stature和avoirdupois兩個屬性,dining和dreanland兩個方法。

  再來看一下Robot類

 

 1public class Robot:Peoplo
 2{
 3    public Robot()
 4    {
 5        //
 6        //TODO: 在此處添加構造函數邏輯
 7        //
 8    }

 9    public string dive()
10    {
11        return " 已經下潛到999米了,馬上就要到1000米勒!";
12    }

13}

  

  我想有必要先搞清楚什麼是基類,Robot由Peoplo派生而來,那麼Robot就是派生類而Peoplo就是基類,也可以這麼說Robot 是Peoplo的派生類,Peoplo是Robot的基類。

  下面我們使用Robot rb=new Robot(),這樣我們得到了一個Robot類型的對象rb,那麼rb都具備什麼成員呢,沒錯,由於Robot繼承了Peoplo類。所以它具備以下成員:stature和avoirdupois兩個屬性,dining和dreanland兩個方法,還有就是自身的dive()方法。我們創建一個Default.aspx頁面來輸出結果驗證一下。

1public partial class _4_Default : System.Web.UI.Page
2{
3       Robot rb = new Robot();
4
5    protected void Page_Load(object sender, EventArgs e)
6    {
7       Response.Write(rb.dining());
8    }

9}

 

  運行結果:今天的紅燒肉真好喫!  

  額的神啊,機器人怎麼開始喫肉了啊,科技再進步機器人也無法喫肉啊,看來Peoplo類中的屬性和方法不一定都適用於Robot啊,人類喫肉是用來補充能量,而機器人用什麼補充能量呢,沒錯,電!看來我們有必要在Robot類中重新定義喫飯這個動作了,有人可能會說我們可以在定義一個RotboDining()方法,其實大可不必!我們只需改造一下Robot和Peoplo類就可以了,如下所示

 

 1public class Peoplo
 2{
 3    public int stature getset; }//身高
 4    public int avoirdupois getset; }//體重
 5    public Peoplo()
 6    {
 7        //
 8        //TODO: 在此處添加構造函數邏輯
 9        //
10    }

11    public virtual string dining()//喫飯
12    {
13        return "今天的紅燒肉真好喫!";
14    }

15    public string dreamland()//睡覺
16    {
17        return "爲什麼不是席夢思的牀墊呢?";
18    }

19}

 

  改造後的Peoplo和原來的沒什麼大的變化,只不過是dining()多了一個virtual關鍵字,它的作用是什麼呢?稍後你就知道了。再來看一下改造後的Robot類,如下所示。

 

 1public class Robot:Peoplo
 2{
 3    public Robot()
 4    {
 5        //
 6        //TODO: 在此處添加構造函數邏輯
 7        //
 8    }

 9    public string dive()
10    {
11        return " 已經下潛到999米了,馬上就要到1000米勒!";
12    }

13    public override string dining()
14    {
15        return "別讓俺幹活,俺在充電中!";
16    }

17}

 

  我們發現改造後的Robot類中多了一個public override string dining()方法,這個方法與基類Peoplo中的dinind()方法簽名一模一樣,而且前面還有一個關鍵字override,先彆着急我們先來運行下Default.aspx頁面看下運行結果,結果如下:

  別讓俺幹活,俺在充電中!

  怎麼樣現在Robot的dining()符合機器人的充電實際效果了吧。他是怎麼實現的呢?

  我們先來看下Robot的public override string dining(),這個方法與基類Peoplo中的dinind()方法簽名一模一樣,而且前面還有一個關鍵字override,這用聲明方法的作用是重寫基類中的dining()方法,這個聲明關鍵就在於關鍵字override,他表示我要重寫基類中的一個方法,那麼要重寫基類的哪個方法呢,這時候方法名dining()就派上用場了,他表示要重寫基類的哪個方法,注意這個方法名一定要和基類中的方法簽名一模一樣(不光是方法名一樣,參數的類型,數量,順序要必須一致),如果這個方法簽名與基類中被重寫的方法簽名不一致會發生錯誤。

  那麼是不是在派生類中能夠將基類中的方法全部都能夠重寫呢,未必!這還要看看基類中的方法是不是可以被重寫,怎麼識別或設置基類中的方法能被重寫呢,我們回過頭來看看改造後的Peoplo類,前面我們說了,改造後的dining()多了一個virtual關鍵字,這個關鍵字的作用就是將此方法定義爲虛方法,這樣派生類就可以重寫這個方法了,簡單的說基類中的方法只有在用關鍵字virtual聲明爲虛方法時,派生類才能夠重寫這個方法。

  那麼當派生類重寫了基類中的虛方法時,我們在調用基類這個方法時該方法會不會執行派生類中被重寫的方法呢?我們來試驗下,我們在default.aspx.cs中分別實例化一個Robot對象rb和Peoplo對象pl,然後分別調用這兩個對象的dining()方法,代碼如下:

 

 1public partial class _4_Default : System.Web.UI.Page
 2{
 3    Robot rb = new Robot();
 4    Peoplo pl = new Peoplo();
 5    protected void Page_Load(object sender, EventArgs e)
 6    {
 7        Response.Write("Robot中的dining()方法:"+rb.dining()+"<br/>");
 8        Response.Write("Peoplo中的dining()方法:"+pl.dining());
 9    }

10}

 

  運行結果: 

Robot中的dining()方法:別讓俺幹活,俺在充電中!
Peoplo中的dining()方法:今天的紅燒肉真好喫

 

  試驗結果表明:雖然在派生類Robot類中重寫了基類peoplo中的dining()方法,但是這並沒有影響到基類中的方法,也就是說派生類中重寫的方法只在派生類中起作用,他並不能改變基類中被重寫的方法。

  關於類的繼承就先談到這裏,說實話很簡單,不過還有一個很重要也比較難以理解的關於實現繼承的構造函數我們沒有談到,我會在下一篇隨筆中簡單的談一下個人關於這方面的理解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章