封裝、繼承、多態並不是針對C#語言提出來的,他是一個在面向對象思想下產生的一個概念。所以想要弄明白封裝、繼承、多態,首先就要先瞭解面向對象概念。封裝:當我們提及面向對象的時候,這個對象怎麼來?就是通過我們人為的封裝得來。封裝就是把一些特征或功能組合到一個抽象的對象上。就比如說電腦:它的特征是有一個顯...
封裝、繼承、多態並不是針對C#語言提出來的,他是一個在面向對象思想下產生的一個概念。所以想要弄明白封裝、繼承、多態,首先就要先瞭解面向對象概念。
封裝:當我們提及面向對象的時候,這個對象怎麼來?就是通過我們人為的封裝得來。封裝就是把一些特征或功能組合到一個抽象的對象上。就比如說電腦:它的特征是有一個顯示屏,有一個主機,有滑鼠和鍵盤等等。功能有計算等。那我們把這些特征和功能組合到“電腦”這個抽象的名詞上時,“電腦”於是就有了這些特征和功能。但這個“電腦”不是實物,它代表所有名叫“電腦”的實物的名稱。在C#中,我們把封裝好的抽象的名詞叫"class",所以我們稱“電腦”叫一個類(class),而實體電腦叫這個類的對象(或者叫實例)。
而繼承、多態則是類的特性。
繼承:這個詞就用正常的語義來解釋就可以了,比如說你繼承了你父親的優點。而在C#中類也是可以繼承的(單繼承),比如說我們有了“電腦”這個類,現在我們再定義一個類叫“聯想電腦”,難道我們要把電腦的特征、功能再定義一遍?可以是可以的,但是這樣一方面代碼有點重覆,另一方向也不方便管理和說明“聯想電腦”的特征。所以我們可以讓“聯想電腦”繼承於“電腦”這個類,我們稱“聯想電腦”為“電腦”的子類或派生類,而“電腦”叫做父類或基類。這樣,只要“電腦”有的東西,“聯想電腦”都有,但是“聯想電腦”還可以進化出(再添加)自己特有的東西。所以,父類(基類)為子類(派生類)的子集。
多態性(polymorphism):是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
實現多態,有二種方式,覆蓋,重載。
- 覆蓋(override),是指子類重新定義父類的虛函數的做法。
- 重載(overload),是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。
其實,重載的概念並不屬於“面向對象編程”,重載的實現是:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然後這些同名函數就成了不同的函數(至少對於編譯器來說是這樣的)。
比如有兩個同名函數:function func(p:integer):integer;和function func(p:string):integer;。那麼編譯器做過修飾後的函數名稱可能是這樣的:int_func、str_func。對於這兩個函數的調用,在編譯器間就已經確定了,是靜態的(記住:是靜態)。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態無關!真正和多態相關的是“覆蓋”。當子類重新定義了父類的虛函數後,父類指針根據賦給它的不同的子類指針,動態(記住:是動態!)的調用屬於子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數地址是在運行期綁定的(晚綁定)。結論就是:重載只是一種語言特性,與多態無關,與面向對象也無關!引用一句Bruce Eckel的話:“不要犯傻,如果它不是晚綁定,它就不是多態。”
那麼,多態的作用是什麼呢?我們知道,封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了——代碼重用。而多態則是為了實現另一個目的——介面重用!多態的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確調用。
註:(本文來自多出轉載1.:http://www.nowamagic.net/librarys/veda/detail/1835)
(本文來自多出轉載2.:http://zhidao.baidu.com/link?url=2IRUVRzvQ_IFgJ3Vkc7JErLABk_8D35qZFpLuJT5JEOCLHh-vfgU-MTXE3bUmu7Y2BTYHqFMikMaPQo0HFjg9LZt9Wmkr5ECH1Gh4vY14Ci)