就c#當中的繼承與多型機制進行了下探索,此處主要根據三個關鍵字進行**:
1. abstract
2. virtual
3. new
針對abstract關鍵字,是抽象之意。用來限定類時,類中的方法,不能有方法體;用來限定方法時,同樣也不能有方法體,並且在子類中除非繼續使用抽象方法,否則必須完成方法體。
針對virtual關鍵字,是虛之意。簡單的用法是用來指示類中的方法可以被子類的同名方法覆蓋或者共存。覆蓋時,子類中使用override關鍵字。共存時,使用new關鍵字。
針對new關鍵字,是新之意。在子類方法中的用法是,用以指示子類中與父類存在的同名方法將在方法表中同父類方法共存,並不覆蓋父類的同名方法。這樣就達到了多型機制下並非一味覆蓋的效果。
我們知道對於類的成員變數來說,存於gc堆內,從低到高,存了所有物件的父類,以及再沿繼承線向上的所有類的類成員變數,這樣的方式,猶如方法錶用new關鍵字構造時的情況。或者說,方法表中的方法,用new關鍵字宣告的時候,其存在形式,就有如子父類的同名成員變數在gc堆裡存在的情況一樣。
這裡舉個簡單的例子:chicken : bird : animal
以上三類中都有乙個成員變數type,為他們自己的小寫類名;都有乙個方法,方法名為showtype()。
此時,我們用override, override , virtual 三個關鍵字來分別宣告這三個類中的方法。之後我們得到了如下結果:
animal chicken1 = new chicken();
bird chicken2 = new chicken();
chicken chicken3 = new chicken();
chicken1.showtype(); //chicken
chicken2.showtype(); //chicken
chicken3.showtype(); //chicken
為什麼會這樣呢?因為在方法表中,chicken物件的方法已經把其所有父類的同名方法全部覆蓋,其父類的同名方法不再存在,任你如何想要輸出其父類的同名方法,都是不可能的。
我們再看下用new , new , virtual 三個關鍵字情況下的顯示情況:
animal chicken1 = new chicken();
bird chicken2 = new chicken();
chicken chicken3 = new chicken();
console.writeline(chicken1.type); //animal
console.writeline(chicken2.type); //bird
console.writeline(chicken3.type); //chicken
chicken1.showtype(); //animal
chicken2.showtype(); //bird
chicken3.showtype(); //chicken
此時我們發現方法的輸出結果和類成員變數的輸出結果相同,我們可以簡單的認為用new關鍵字宣告的方法,具有成員變數類似的操作性質。其實,在同名的類成員變數宣告時,編輯器會主動提醒你加上new關鍵字來隱藏父類的同名變數,此處我們就發現了用new時,成員變數和方法的繼承或多型的行為方式一致。
一、繼承
大致內容在繼承本質論中都已經闡述,這裡簡單再進行回顧。
在.net中,繼承按照實現方法不同分類如下:
----實現繼承:派生類繼承了基類的所有屬性和方法;
----介面繼承:派生類繼承了介面的方法簽名。
下面羅列一些對繼承的認識:
1.繼承是可以傳遞的,子類對父類的拓展,必須繼承父類的方法(當然,覆蓋也是可以的,那就是多型的內容),同時可以新增新的內容(無限制的繼承會導致子類物件的無限增大,所有,並不推薦在所有情況下都是用繼承的方式實現方法的繼承,可以使用介面)。
2.子類可以呼叫父類的方法和字段,父類不可以呼叫子類的方法和字段。簡單的說就是有父親不一定有兒子,有兒子一定有父親。
3.利用虛方法或者抽象方法,可以令子類覆寫父類的方法,要注意的是,其本質就是發生在loader heap中方法表的變化。
4.子類不光繼承父類的公有成員,同時繼承父類的私有成員,只是在子類中不被訪問。所有,如果當物件的訪問許可權發生變化時(型別轉化為父類),既可以訪問。
5.new關鍵字在虛方法中的阻斷作用。就如同子類和父類擁有同名屬性一樣的效果。
繼承的金科玉律:
1.密封類不可以被繼承;
3.實現單繼承,介面多繼承;
4.從巨集觀上看,繼承多關注於共通性;而多型著眼於差異性;
5.繼承的層次應該有所控制,否則型別之間的關係維護會消耗更多精力;
6.物件導向的原則:多組合,少繼承;高內聚,低耦合。
二、封裝
封裝的意義:
1.隱藏系統實現的細節,保證系統的安全性和可靠性;
2.提供穩定不變的對外介面。因此系統中相對穩定的部分常被抽象為介面;
3.封裝保證了**的模組化,提高了軟體的復用和功能分離。
封裝的規則:
--盡可能呼叫類的訪問器,而不是成員,即使在類的內部;
--內部私有部分可以任意改,但是一定要在保證外部介面穩定的前提下;
--將對字段的讀寫控制實現為屬性而不是方法,否則非明智之舉;
--深刻理解public , private , internal , protected關鍵字;
--封裝的精華是封裝變化。《軟體設計精要與模式》--張逸
下面來體驗下封裝與不封裝的區別:兩端**
part one:
public class people
part two:
public class people
set }
public string e-mail
set $")) e-mail = value; }
} }
可以感受到以上兩種書寫方式的區別嗎?
三、多型
在以上密境尋蹤中有詳細述說,這裡就略去。
C 的繼承與多型
概念介紹 繼承 為了 的重用,保留基類的原本結構,並新增派生類的部分,同時可能覆蓋 overide 基類的某些成員。多型 一種將不同的特殊行為和單個泛化記號相關聯的能力,分為靜態多型和動態多型。繼承 乙個派生類可以通過繼承獲得基類的所有成員,而無需再次定義它們。分為public protected和...
C 的繼承與多型
概念介紹 繼承 為了 的重用,保留基類的原本結構,並新增派生類的部分,同時可能覆蓋 overide 基類的某些成員。多型 一種將不同的特殊行為和單個泛化記號相關聯的能力,分為靜態多型和動態多型。繼承 乙個派生類可以通過繼承獲得基類的所有成員,而無需再次定義它們。分為 public protected...
C 繼承與多型
派生類繼承基類 又稱父類 超類 的屬性和方法,在此基礎上可以進行修改或新增新的屬性和方法。class 派生類名 繼承方式 基類名 為了保護基類的資料封裝性,無論哪種繼承方式,積累的私有成員在派生類中都是不可見的。1.public繼承 基類的訪問許可權在派生類中不變。公有還是公有,保護還是保護,派生類...