OC中沒有抽象基類和接口的存在,而是使用的協議。作為C面向對象化的語言,肯定具備OOP的絕大多數的賣點。
先說說抽象基類和接口,兩者不同:
抽象基類(Abstract Class),俗稱ABC。接口(Interface),俗稱也是接口。兩者都實現了OO中的繼承機制。也都是通過定義抽象方法去實現對繼承類功能上的約束。
抽象基類可以為部分方法提供默認的實現,可以定義字段屬性,從而避免子類的重復實現,可提高代碼的可重用性,這是抽象類的優勢;而接口只能包含抽象方法。
何時使用抽象基類何時使用接口關鍵還是取決于待繼承之間的聯系。側重于它們之間的個性差異還是共性聯系。
當個性大于共性。差異較大的個性間具有某些相同的行為,相同行為的實現方式有較大的區別,使用接口。
當共性大于個性,共性相同的個體間必然具備相同的屬性與行為,相同行為的實現方式具有一定區別,使用抽象基類。
總結如下:
當在差異較大的對象間尋求功能上的共性時,使用接口。
當在共性較多的對象間尋求功能上的差異時,使用抽象基類。
在OC中,只提供了協議,然后,本文的重點則是,怎么去構建上面說的那些,接口的話,在OC中等同協議就好了,當然OC中的協議不是必須都要實現的,還有一些協議在運行時添加成員變量,直接在協議中添加屬性,為的就是想要getter setter方法。都不在討論的范圍內。
有以下例子,假如有人、魚、青蛙三個對象。每個對應的類,都有個游泳的方法。再有個數組,里面放著前面的三個類。數組內的對象數量、順序不限。
要求就是遍歷這個數組,得到人的對象,就調用人游泳的方法。得到魚的對象,調用魚游泳的方法,等等。
好吧,然后你就去看代碼。首先for內得到一個對象,然后一口氣上來了三個if,去判斷這個對象屬于哪個類型,再然后調用相應的游泳方法。如果對象的類型擴充到10個、100個,然后就可以看到很壯觀的二三百行的if代碼。真是爽上天的節奏,復制黏貼也要不少時間吧。
回歸剛才的透劇,協議的擴充,至于為什么沒用抽象基類,看上面的總結,和下面舉例子時對象之間的聯系。
創建一個游泳的協議,并且提供一個游泳的方法(抽象方法),分別讓人、魚、青蛙三個類遵守這個協議,并且實現游泳的方法。在遍歷數組的時候聲明一個id類型并且遵守這個協議的變量指向得到對象,而不用去判斷對象類型,直接調用游泳的方法。
oop的繼承、封裝、多態。大多都是知道,用的時候并不多,蛋疼的事,以上就是不算擴充的擴充。多是在處理mvc中的view時用到,比如有兩三種cell的時候等等。
然后再說 抽象基類。
OC中 定義一個類,繼承某個協議。此類用作基類。就能當抽象基類使用。(其實,直接一個基類,然后讓子類分別重寫對應的方法也能解決。畢竟接口就是很特殊的抽象基類)
同樣上例子
鯉魚、鯽魚、草魚三種。也要游泳。對象之間的共性(都是魚)大于個性(略微不同的游泳方式)。
這里的游泳是直接基類提供還是使用協議,看個人愛好。鑒于繼承開銷很大,而平時從事的項目,也并不是特大,特封裝,特面向對象思想。我使用協議。區別自然是有的。不多做學術上的講解和爭論。
此例中 首先要有個基類,魚的類。三種魚都繼承與魚基類。然后基類遵守游泳協議。一切看起來很美好,和上面的例子也沒什么區別。抽象基類的優勢在對象的狀態上,也就是俗稱的屬性、成員變量等。每個魚都有魚鱗,魚尾。甚至每個魚的子類對象都有的行為:呼吸。這時候,魚鱗、魚尾類似的屬性,表示對象狀態的這些都添加到基類 魚 類里面。呼吸的方法同樣也添加在基類里面。子類,自然也繼承到了,提高了代碼的復用性,而不是每個子類都添加屬性和方法。
面向對象的三大法寶,封裝,繼承,多態。上面的例子談得多的也是用繼承去實現多態。嚴格的來說,封裝性的良好才最能體現面向對象的這一理念。繼承剛好是破壞封裝性的行為,因為基類內部對子類可見。
在最后說些設計相關的
優先使用組合而非繼承!
優先使用組合而非繼承!!
優先使用組合而非繼承!!!
重要的事說三遍。