.NET Core CSharp 初級篇 1 6 本節內容為類的多態與繼承 簡介 終於講到了面向對象三大特性中的兩大特性——繼承與多態。通過繼承與多態,我們能很好的將類的拓展性發揮到了極致。在下麵的內容講解中,我們將從各個方面對繼承和多態進行刨析。 繼承 繼承事實上是一個非常好理解的語法,在C 中實 ...
.NET Core CSharp初級篇 1-6
本節內容為類的多態與繼承
簡介
終於講到了面向對象三大特性中的兩大特性——繼承與多態。通過繼承與多態,我們能很好的將類的拓展性發揮到了極致。在下麵的內容講解中,我們將從各個方面對繼承和多態進行刨析。
繼承
繼承事實上是一個非常好理解的語法,在C#中實現繼承使用A:B,表示A類繼承B類。子類(一稱為派生類)繼承於父類(一稱為基類)就好比孩子繼承了父親的一切,但是孩子總歸是有自己的個性的,而父親也有一些不會告訴孩子的事情。如果我們從之前的訪問控制符這一部分進行理解的話,你可以這樣描述這個“融洽”的父子關係。
假定有以下這個例子:塞巴斯蒂安·艾奎斯(父類)是一個歐洲宮廷的貴族,67歲,他是一個子爵,並且掌握了一個驚天大秘密不能告訴任何人,只能爛在肚子里。他育有一子名叫麥克·艾奎斯,由於塞巴斯蒂安·艾奎斯年老體弱,當家裡需要錢的時候,他會讓自己的兒子帶上銀行卡前往atm機取錢。兒子的車和他的車一模一樣,每次兒子讓管家開車的時候都必須說清楚:“我要開我父親的車。”,或者:“今天我開我自己的車”。如果他沒有說,那麼管家會預設的取出兒子的車。他家還有一個大莊園閑置可以用於開發,只要父親同意,那麼兒子可以自由開發。
對於這個例子,你需要得出的結論是:
- 如果塞巴斯蒂安·艾奎斯(父類)沒有出生,那麼麥克·艾奎斯(子類)也不存在。(子類實例化時必定先調用父類構造方法)
- 對於塞巴斯蒂安·艾奎斯(父類),他的名字屬於大家都可以知道的(public),誰都可以輕易的得到。但是想擁有這個名字,卻只能是他的家族的人才可以(繼承後才能獲得父類的欄位)。
- 對於前往ATM機取錢這件事,取款密碼只可能告訴他的兒子,別人是不能得到的。(protected可以被子類訪問,但是其餘不可訪問)
- 塞巴斯蒂安·艾奎斯(父類)知道一個秘密,這個秘密只有他本人才知道(private),包括他的兒子也不可能知曉(子類無法獲取private)
- 因為父子倆的車一模一樣,取車需要特別說明(子類和父類函數簽名一致時,父類函數預設會隱藏,除非顯式的說明)
- 大莊園是父親的,但是可以被兒子取改造(父類函數指定為virtual時,子類可以重寫父類函數)
通過這一些刨析,我認為你應該已經清楚了七八分繼承的意思了。這裡需要介紹一下我們的base關鍵字,base關鍵字在子類中體現為調用父類的方法。
特別的,你需要註意的是,C#對於類與類的繼承只支持單繼承,如果你試圖實現多繼承,你可以使用介面作為媒介和橋梁。
我們現在用一段代碼演示完我們的繼承,我們這個教程更多的是引導你去思考,而不是讓你如同一些速成培訓班出來的一樣,沒有獨立的思考能力。
class Father
{
public Father()
{
Console.WriteLine("Father Method");
}
private string MSGSecret;
protected string BankSecret;
public string Name;
public string Car;
protected void test()
{
}
}
class Son:Father
{
public Son()
{
Console.WriteLine("Son Method");
}
//隱式的生成了這三個欄位
//protected string BankSecret;
//public string Name;
//public string Car;
public string Car;
public void getCar()
{
base.Car;//父類
this.Car;//子類
base.test()//調用父類方法,如果簽名不衝突,可以省略base
}
}
Son s = new Son();//思考一下這裡會輸出什麼?
多態
多態是一個並不困難的東西,在繼承和介面中我們講到的重寫其實就是多態性的一種類型了。之前我們簡單的舉過一個例子來說明多態:人和鯉魚都是動物,但是人用肺進行呼吸,而鯉魚用鰓進行呼吸。這個例子就很好的體現了多態。利用下麵這段代碼來解釋吧。
class Animal
{
//通過抽象方法實現多態
abstract void Breathing();
//虛方法實現多態
virtual void Eat()
{
}
}
class Human:Animal
{
override void Breathing()
{
}
override void Eat()
{
}
}
class Fish:Animal
{
override void Breathing()
{
}
new void Eat()
{
}
}
Animal ah = new Human();
Animal af = new Fish();
Fish f = new Fish();
註意看最後幾行,ah和af各屬於Human和Fish的對象,但是當方法調用的時候,統一調用父類中的方法,並且載入子類中的重寫和實現。
ah.Eat();//調用父類的Eat(),但是以Human類中的重寫方法為實現
af.Eat();
f.Eat();
這三者的區別在哪裡?事實上你只需要知道,多態性就是通過父類去管理子類,讓子類遵循父類的規範。當子類使用從父類繼承的方法的時候,是去調用父類的方法,但是使用子類的實現。特別的,如果你在方法中使用new修飾符,那麼這個方法將會和父類毫無關係,就如這個單詞的意思一樣,這是一個新的函數,不是父類中的函數。現在你可以試著分析上述三個函數調用的各是哪個類中的方法。
多態最大的有點就是你可以通過一個基類或者介面去管理所有繼承於他們的子類的函數方法,並且同一個函數可以有多種實現方法。
如果你使用介面和抽象類去實現多態,實現的方法也是一樣的,只不過是基類型無法實例化。