close

類別的繼承

 

1. 子類別與父類別:

子類別(又稱「衍生類別」)和父類別(又稱「基礎類別」)這兩個名詞,隨著「繼承」這個動作的發生,而一起被定義。我們稱繼承者是子類別,被繼承者是父類別。「子類別繼承父類別」這句話,其意義是「父類別將自己的publicprotected的成員與成員函式傳遞給子類別,使子類別在宣告時不必宣告這些成員、成員函式,就能擁有他們」。

子類別的宣告式:

class 子類別名稱 : 父類別名稱

{

    類別成員宣告式

    類別成員函式宣告式

    類別建構式    

};

註:在子類別宣告式之內,可用this關鍵字來代表類別本身,而用base關鍵字來代表其父類別(可用base.成員base.成員函式名稱(參數一,參數二…)來呼叫父類別的成員與成員函式)。

再次強調,父類別中能夠被繼承的只有「publicprotected的成員與成員函式」。而父類別的建構式,就算其為public也不能被子類別繼承。子類別之建構式的寫法與一般類別不同(與其父類別的建構式有關),語法為:

存取修飾詞 子類別名稱(參數資料型態一 參數一, 參數資料型態二, 參數二…) : base(父類別建構式參數一, 父類別建構式參數二…)

{

//函式內容(可以不需對賦類別建構式參數進行設定)

}

此語法之形式不易理解,可參考範例:

class person    

{

      public string name;

      public int age;

      public person(string n_, int a_) 

      { name = n_; age = a_; }

      public string self_introduction()

 { return "hi, I'm " + name + "," + age + "years old."; }

};

class boy : person    //boy是一個子類別,繼承了父類別person

{

      public int money;

      public boy(string n_, int a_, int money_) : base(n_, a_)

      { money = money_; }  //子類別建構式在此

};

boy b1 = new boy("Jack", 12, 200);  //子類別物件之宣告,仍按照子類別建構式的寫法

 

2. 在子類別重新定義父類別成員函式:

當子類別從父類別繼承了某個成員函式,但卻想改寫這個成員函式時(這個「改寫」,並不會影響父類別物件對該成員函式的使用,而是重新在子類別中定義該成員函式,以供子類別自己所用),有以下兩種方法:

(1) 子類別覆寫父類別的虛擬成員函式:

要成功使用這個方法的前提是:父類別中那個要被重新定義的成員函式,是個「虛擬函式」。虛擬函式的寫法需利用到virtual關鍵字,如下:

存取修飾詞 virtual 回傳資料型態 虛擬成員函式名稱(參數資料型態一 參數一, 參數資料型態二, 參數二…)

{

//函式內容

}

而在子類別中,覆寫該虛擬函式需利用override關鍵字。語法如下:

存取修飾詞 override 回傳資料型態 虛擬成員函式名稱(參數資料型態一 參數一, 參數資料型態二, 參數二…)

{

//函式內容

}

※ 範例如下:

class A

{ public virtual string intro(){ return "this is A";}};

class B : A

{ public override string intro(){ return "this is B"; }};

B b1 = new B();

textBox1.Text = b1.intro();   //顯示this is B

(2) 子類別成員函式直接取代父類別成員函式:

這種方法比較方便,直接在子類別中利用new關鍵字宣告欲取代的成員函式。語法為:

存取修飾詞 new 回傳資料型態 虛擬成員函式名稱(參數資料型態一 參數一, 參數資料型態二, 參數二…)

{

//函式內容

}

※ 範例如下:

class A

{ public string intro(){ return "this is A";}};

class B : A

{ public new string intro(){ return "this is B"; }};

B b1 = new B();

textBox1.Text = b1.intro();   //顯示this is B

 

3. 父類別物件與子類別物件的轉換:

(1) 父類別物件,不能顯性轉換為子類別物件。

(2) 子類別物件,可以顯性轉換為父類別物件。只不過轉換之後,在該子類別內另行定義的成員和成員函式,將會消失。只有繼承父類別的成員和成員函式會保留下來。顯性轉換的方法為:

(父類別名稱)子類別物件名稱

如,今有一個person類別和一個man類別(man 類別繼承person類別,故person是父類別相對於man是子類別),一個man類別物件名為wang,則:

person jili_wang = (person)wang;

即可將wang轉成person類別後,儲存在jili_wang這個perosn類別物件裡。

 

4. 抽象類別與抽象成員函式:

所謂抽象成員函式」,指的是在該成員函式被宣告時,只有宣告其名稱、回傳資料形態、參數列,卻沒有宣告函式內容(函式內容不在類別本身中宣告,而是在該類別之衍生類別中再去覆寫)。而若某個類別擁有抽象成員函式,就稱其為「抽象類別」(抽象成員函式也只能在抽象類別中宣告)。抽象類別並不能被用來建立物件,而是專門被用來繼承的。這種用法,在較大、複雜的類別架構中,能使程式碼更為簡潔易讀。

抽象類別與抽象成員函式均用到關鍵字abstract。其宣告如下:

(1) 抽象類別的宣告:

abstract class 類別名稱

{

    類別成員宣告式

    類別成員函式宣告式

    類別建構式    

};

(2) 抽象成員函式的宣告:

abstract 存取修飾詞 回傳資料型態 成員函式名稱(參數資料型態一 參數一, 參數資料型態二, 參數二…)

※ 註:抽象類別中可以沒有抽象成員函式,但有抽象成員函式的類別一定要宣告成抽象類別,否則程式執行時會出錯。

(3) 抽象成員函式的實作:

抽象成員函式的函式內容不在抽象類別本身中宣告,而是在該抽象類別之衍生類別中去覆寫。「為抽象成員函式寫入函式內容」這個動作,稱為對抽象成員函式的「實作(implement)」。

如以下範例:

abstract class person

{

      public string name;

      public int age;

      public person(string n_, int a_)

      { name = n_; age = a_; }

      abstract public string talk();       //抽象成員函式talk()在此   

};

class teacher : person  

{

      public teacher(string n_, int a_)

          : base(n_, a_){ }

      public override string talk()   //實作抽象成員函式talk()

      { return "Hi, My name is " + name + ", nice to meet you!"; }

};

class waiter : person

{

      public waiter(string n_, int a_)

          : base(n_, a_){  }

      public override string talk()    //實作抽象成員函式talk()

      { return "Welcome to our bar. Need something?"; }

};

由上範例可知,每個衍生類別對於抽象成員函式都有不同的實作方法,就如同生活中對於每種不同的人(person)進行交談(talk)時,他們的回話都不盡相同。這就是抽象成員函式在應用上的意義。

 

 

 

上一篇:類別物件的複製

下一篇:資料夾的處理

按此前往C#完整教學目錄

arrow
arrow

    埃伯 發表在 痞客邦 留言(0) 人氣()