物件導向中最常提到的就是對象,類,執行個體這些,
既然是物件導向的話,那先從對象談起,
對象
首先,一切事物皆為對象,對象是一個實體,其可以包含自己的特性和特定的行為。
類
就是將一些對象所具有的相同屬性和相同的行為進行提取出來,也就是抽象,
提取出來後便會組成一個集合,那麼這個集合就是類,
所以類,也可以理解為是對類似的對象分類的意思。
執行個體
就是一個真實的對象,由於前面使用類來對對象進行了分類,提取了他們相似的屬性和行為,
所以,其滿足於這個類,也就是可以通過這個類來產生對應的執行個體,這就是所謂的執行個體化,
比如,一個人可以用一個類來描述,這個類應該有頭髮顏色,膚色,身高等等這樣的屬性,
然後還會有如走路,吃飯這樣的行為,那麼,便可以通過 new 這個人類來產生一個執行個體,
這就是執行個體化一個人類的執行個體。
建構函式
建構函式是用來對類實現初始化的,其沒有傳回值,在通過 new 一個執行個體的時候自動調用建構函式
需要提及的是,任何一個類都有建構函式,如果沒有自訂建構函式的話,
系統會調用預設的建構函式來實現執行個體化對象,當然,如果自訂了建構函式的話,
那麼系統預設的建構函式就失效了。
解構函式
一個類中只能有一個解構函式,且解構函式無法被繼承和重載,
同時,無法使用程式調用解構函式,因為解構函式是自動被調用的,也就是程式員是無法控制何時調用解構函式的,
因為這是由記憶體回收行程決定的,記憶體回收行程檢查是否存在應用程式不再使用的對象,
如果記憶體回收行程認為某個對象符合析構,則調用解構函式,並且回收記憶體,
當程式退出時也會調用解構函式來回收記憶體。
屬性
屬性是一個方法或一對方法,但是在訪問它的代碼來看,它卻是一個欄位,而不是一個方法,
比如,在調用方法時,一般都是 . FunctionName(),而在訪問欄位時確是 . FieldName,
屬性有兩個方法,一個是用來設定值的 set(),一個是用來擷取值的 get(),
可以通過這兩個方法來實現對一個欄位的存取控制,
比如唯讀控制(即只有 get 方法),
唯寫控制(即只有 set 方法)或者是可讀可寫(既有 set 方法,又有 get 方法)。
封裝
每一個對象都包含了它能進行操作所需要的所有的資訊,
所以,一個對象不必依賴其他對象來完成自己的操作,
這裡的意思就是一個對象是可以獨立存在的,
比如,一隻狗,它可以將自己的名字,重量等資訊封裝起來,
這樣這隻狗便是一個完整的對象,是可以獨立存在的,而不必依賴其他的動物。
封裝的優點體現在:良好的封裝是可以減少耦合的,類內部的實現是獨立的,類具有清晰地對外介面。
繼承
繼承就是一種“是一個”的關係,也就是說,一個對象是另外一個對象的一部分,
如果單就功能來說的話,繼承也可以理解為是功能上的擴充,比如原來的類的功能只是走路,
那麼我可以通過繼承原來的類,然後再在這個子類中添加一個跑步的類,這樣就實現了功能的擴充,
也就是子類可以完成包括父類所有的功能在內的更多功能。
子類既然繼承了父類,那麼子類便繼承了父類中的方法,欄位,屬性,事件,索引器等,
但是其中有一個是例外的,就是建構函式是不能被繼承的,其只能被子類調用,而不能繼承。
繼承的優點體現在:修改和複用方便,代碼得到共用,同時對擴充也是比較方便的,
但是繼承濫用會出現一系列的問題:這是因為繼承破壞了封裝性,
從上面的繼承關係來看,父類的非私人成員在子類中是可以完全訪問的,
這樣便增大了兩個類之間的耦合度(繼承是一種類與類之間的強耦合關係)。
然後,繼承還有一個最大的缺點,那就是只要是父類改變了,
那麼子類不得不變(因為其完全繼承了父類)。
多態
多態表示的是不同的對象可以執行相同的動作,但要通過他們自己的實現代碼來執行。
換句話說就是子類可以以父類的身份出現,但是在動態運行時,其執行的卻是自己的代碼,
但是需要注意的是,當子類以父類的身份出現時,子類中特有的屬性和方法是便可以使用的。
為了使子類的執行個體完全接替來自父類的類成員,父類必須將該成員聲明為虛擬,
這個可以通過關鍵字 Virtual 來實現,然後,子類可以通過使用 override 關鍵字來重寫父類中定義的方法,
也就是以自己的方式來實現父類中定義的方法。
多態的原理是當方法被調用時,無論對象是否被轉換為其父類,
都只有位於對象繼承鏈最末端的方法實現會被調用,
也就是說,虛方法是按照其運行時類型而非編譯時間類型進行動態綁定調用的。
抽象類別
C# 中是可以使用抽象類別和抽象方法的,抽象類別有如下的特定:
其不能被執行個體化,
抽象類別中定義的抽象方法必須在其子類重寫,
只要是類中包含了一個及以上的抽象方法,那麼這個類就是抽象類別,必須用 abstract 描述類
介面
介面呢,是一個功能集合,一旦類實現了介面,類就可以支援介面所指定的所有屬性和成員,
在聲明介面時,是不允許提供介面中任何成員的執行方式的,所以介面是不能執行個體化的,並且不能有修飾符。
如果一個類實現了一個介面,那麼這個類就必須要實現介面中的所有的方法和屬性。
下面呢就是通過一個整體的 Demo 來實現上面的關於物件導向的基礎部分的演練:
上面的例子中呢,有 Duck(鴨子這個抽象類別),然後其下面有三個子類,
分別是天鵝(Swan),笨鴨(FoolDuck),玩具鴨(ToyDuck),
所有的鴨子都是會遊泳的,所以直接把 Swim()方法寫在了父類 Duck 中,
這樣所有繼承自 Duck 類的子類均會遊泳了,因為都會有 Swim()這個方法。
然後,還定義了兩個介面,一個是 Fly(也就是能不能飛行),還有一個就是 Quack(即能不能發出發出叫聲),
然後定義了兩個類來實現介面 Fly ,兩個類的行為分別是能夠飛和不能夠飛,
然後就是定義了三個類來實現介面 Quack ,這三個類分別代表發出 GuaGua 聲音,和發出 ZhiZhi 聲音,
還有一個就是不會發出聲音了。
下面就開始來寫類了
首先,完成後的項目架構為
下面就來一個一個的看代碼了
先是 Fly 介面
然後是實現了這個介面的兩個類 CanFly 和 FlyNoWay
介面 Quack 即叫聲部分的代碼
實現了 Quack 介面的三個類
然後就是來看核心的 Duck 類了
最後就是繼承自 Duck 類的三個子類了
再來看一下用戶端的代碼吧
上面就是整個 Demo 的所有代碼了,
下面在給出效果吧