一個面向對象的語言在處理對象時,必須遵循的三個原則是:封裝、繼承和多態。
(1)封裝
所謂“封裝”,就是用一個框架把數據和代碼組合在一起,形成一個對象。遵循面向對象數據抽象的要求,一般數據都被封裝起來,也就是外部不能直接訪問對象的數據,外部能見到的只有提供給外面訪問的公共操作(也稱接口,對象之間聯系的渠道)。在C#中,類是對象封裝的工具,對象則是封裝的基本單元。
封裝的對象之間進行通信的一種機制叫做消息傳遞。消息是向對象發出的服務請求,是面向對象系統中對象之間交互的途徑。消息包含要求接收對象去執行某些活動的信息以及完成要求所需要的其他信息(參數)。發送消息的對象不需要知道接收消息的對象如何對請求予以響應。接收者接收了消息,它就承擔了執行指定動作的責任,作為消息的答復,接收者將執行某個方法,來滿足所接收的請求。
封裝其實就是信息隱藏,隱藏一個對象的本質,讓用戶不再注意那些細節.提供一些向外的接口供別人使用。 就像電視的內部已經被封起來,你不需要知道它的內部是由哪些零件組成、如何工作。你只知道用遙控器來控制就好。
(2)繼承
世界是復雜的,在大千世界中事物有很多的相似性,這種相似性是人們理解紛繁事物的一個基礎。因數事物之間往往具有某種“繼承”關系。比如,兒子與父親往往有許多相似之處,因數兒子從父親那里遺傳了許多特性;汽車與卡車、轎車、客車之間存在着一般化與具體化的關系,它們都可以用繼承來實現。
繼承是面向對象編程技術的一塊基石,通過它可以創建分等級層次的類。例如,創建一個汽車通用類,它定義了汽車的一般屬性(如:車輪、方向盤、發動機、車門等)和操作方法(如:前進、倒退、剎車、轉變等到)。從這個已有的類可以通過繼承的方法派生出新的子類,卡車、轎車、客車等,它們都是汽車類的更具體的類,每個具體的類還可以增加自己一些特有的東西。繼承是父類和子類之間共享數據和方法的機制,通常把父類稱為基類,子類稱為派生類。一個基類可以有任意數目的派生類,從基類派生出的類還可以被派生,一群通過繼承相聯系的類就構成了樹型層次結構。
如果一個類繼承兩個或兩個以上直接基類,這樣的繼承結構被稱為多重繼承或多繼承。
盡管多繼承從形式上看比較直觀,但在現實上多繼承可能引起繼承操作或屬性的沖突。當今的很多語言已不再支持多繼承,C#語言也對多繼承的使用進行了限制,它通過接口來實現。接口可以從多個基接口繼承。接口可以包含方法、屬性、事件和索引器。一個典型的接口就是一個方法聲明的列表,接口本身不提供它所定義的成員的實現。所以接口不能被實例化,一個實現接口的類再以適當的方法定義接口中聲明的方法。
有僅如此,C#的接口概念十分適用於組件編程。在組件和組件之間、組件和客戶之間都通過接口進行交互。繼承可以理解為基類代碼的復用. 當一個對象可以描述為另外一個對象的時候用繼承(is-a)的關系. 當一個可以可以有另外一個對象的時候用組合(has-a)的關系. 當一個對象可以包含某個行為的時候用接口(can-do)的關系.
(3)多態性
多態性就其字面上的意思是:多種形式或多種形態。在面向對象編程中,多態是指同一個消息或操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。例如,問甲同學:“現在幾點鍾”,甲看一看表回答說:“3點15分”,又問乙同學:“現在幾點鍾”,乙想一想回答說:“大概3點多鍾”,又問丙同學:“現在幾點鍾”,兩干脆回答說:“不知道”。這就是同一個消息發給不同的對象,不同的對象可以做出不同的反應。
同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果, 這就是多態性。多態性通過派生類重載基類中的虛函數型方法來實現。 C#支持兩種類型的多態性 編譯時的多態性為我們提供了運行速度快的特點,而運行時的多態性則帶來了高度靈活和抽象的特點。 編譯時的多態性 編譯時的多態性是通過重載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的參數、返回的類型等信息決定實現何種操作。 運行時的多態性 運行時的多態性就是指直到系統運行時,才根據實際情況決定實現何種操作。C#中,運行時的多態性通過虛成員實現。
////需要熟練掌握 abstract,virtual,override,new,sealed,base的用法. #region abstractClass 抽象類 /// <summary> /// 抽象類 /// 可以將類聲明為抽象類。方法是在類定義中將關鍵字 abstract 置於關鍵字 class的前面 /// </summary> public abstract class abstractClass { private string mclassName; /// <summary> /// 抽象類構造方法 /// </summary> /// <param name="mclassName"></param> public abstractClass(string mclassName) { this.mclassName = mclassName; } #region ClassName 抽象屬性 /// <summary> /// /// </summary> public virtual string ClassName { get { return mclassName; } } #endregion #region DoWork 抽象方法 /// <summary> /// 抽象方法 /// 1.抽象類也可以定義抽象方法。方法是將關鍵字 abstract 添加到方法的返回類型的前面。 /// 2.抽象方法沒有實現,所以方法定義后面是分號,而不是常規的方法塊。 /// 3.抽象類的派生類必須實現所有抽象方法。當抽象類從基類繼承虛方法時,抽象類可以使用抽象方法重寫該虛方法。 /// </summary> /// <param name="i"></param> public abstract void DoWork(int i); #endregion #region DoWork 虛方法 /// <summary> /// virtual 關鍵字用於修飾方法、屬性、索引器或事件聲明,並使它們可以在派生類中被重寫。 /// 1.virtual 修飾符不能與 static、abstract、private 或 override 修飾符一起使用。 /// 2.在靜態屬性上使用 virtual 修飾符是錯誤的。 /// 3.除了聲明和調用語法不同外,虛擬屬性的行為與抽象方法一樣。 /// 4.通過包括使用 override 修飾符的屬性聲明,可在派生類中重寫虛擬繼承屬性。 /// </summary> /// <param name="message"></param> public virtual void DoWork(string message) { } #endregion } #endregion #region DemoClass 繼承抽象類 派生類 /// <summary> /// 派生類可以包含與基類方法同名的方法 ///1.基類方法必須定義為 virtual。 ///2.如果派生類中的方法前面沒有 new 或 override 關鍵字,則編譯器將發出警告,該方法將有如存在 new 關鍵字一樣執行操作。 ///3.如果派生類中的方法前面帶有 new 關鍵字,則該方法被定義為獨立於基類中的方法。 ///4.如果派生類中的方法前面帶有 override 關鍵字,則派生類的對象將調用該方法,而不是調用基類方法。 ///5.可以從派生類中使用 base 關鍵字調用基類方法。 ///6.override、virtual 和 new 關鍵字還可以用於屬性、索引器和事件中 /// </summary> public class DemoClass : abstractClass { private string motherName; #region DemoClass base的用法 /// <summary> /// 子類繼承父類(抽象類)的構造方法 /// </summary> /// <param name="mclassName"></param> /// <param name="motherName"></param> public DemoClass(string mclassName, string motherName) : base(mclassName) { this.motherName = motherName; } #endregion #region ClassName 實現抽象屬性 /// <summary> /// /// </summary> public string OtherName { get { return motherName; } } #endregion #region DoWork /// <summary> /// /// </summary> /// <param name="i"></param> public override void DoWork(int i) { } #endregion } #endregion #region sealedClass 密封類 /// <summary> /// 1.在class前使用 sealed 修飾符時會阻止其他類從該類繼承. /// 2.在重寫基類中的虛方法或虛屬性的方法或屬性上使用.則他的繼承類無法重寫相應的方法或屬性. /// </summary> public sealed class sealedClass : abstractClass { public sealedClass(string mclassName) : base(mclassName) { } #region DoWork 密封方法 /// <summary> /// /// </summary> /// <param name="i"></param> public sealed override void DoWork(int i) { } #endregion } #endregion