protocol category和繼承的區別

2021-07-02 04:21:01 字數 2424 閱讀 5390

protocol、category和繼承的區別

類別是用在給乙個類擴充套件方法,不用儲存變數,因為類別不能儲存變數 整合擴充套件方法和變數。比較重一些。類別 category 相對輕量一些。當時不能完全替代整合。

利用繼承,多型是乙個很好的保持「對擴充套件開放、對更改封閉」(ocp)的辦法,也是最常見的一種方法。objective c還支援另外兩種語法來支援ocp:protocol和category。protocol只能定義一套介面,而不能提供實現,變相的也是一種abstract class的實現方式(oc 語法上本身不支援抽象基類)。category可以為類提供額外的介面和實現。那麼到底三者(繼承, protocol,category)在使用上到底有什麼本質的區別呢?在我看來,protocol的作用是為一些列類僅僅提供一套公用的介面,而完全沒 有辦法也沒可能去提供具體的一些實現情況;category則是為乙個已有的類提供一些額外的介面和具體實現;而繼承則基於兩者之間,既可以想 protocol一樣提供只是純粹提供介面,也可以像category一樣提供完整的實現,而且繼承還能對類以後的功能進行改寫,所以說繼承的力量是最強 大的。那麼具體在使用的時候各自都適合什麼樣的情況呢?

.        protocol是定義行為而不管誰去怎麼實現,這是一種比較灑脫和不負責的情況,就好像在外包專案中的客戶一樣,他只是他需要什麼什麼東西,具體實現他不會也不能給出一樣。delegate datasource這樣的就用protocol實現比較好

.        category是對乙個功能完備的類的一種補充,就像是乙個東西的主要基本功能都完成了,可以用category為這個類新增不同的元件,使得 這個類能夠適應不同情況的需求(但是這些不同需求最核心的需求要一致)。找個就像你已經有了一輛能夠開動的汽車一樣,我們可以用category為你的汽 車新增各種之前沒有的功能,最後讓這輛汽車變成超級跑車一樣。

.        當某個類非常大的時候,category可以按不同的功能將類的實現分在不同的模組中實現。

.        繼承則是都可以完成上面的工作,但是繼承有很大的代價問題,一是通過繼承來進行擴充套件是一種耦合很高的行為,對父類可以說是完全依賴;二是繼承由於 對父類依賴,所以開發代價相對大,要求對父類的工作流程相對熟悉;三是繼承體系如果太複雜會導致整個系統混亂,難以維護。所以在能夠用上面兩種方法完成擴 展的時候,就千萬不要使用繼承。什麼情況才是迫不得已要使用繼承呢?那就是如果你既想提供一系列介面的定義,同時又想提供一些但是又不能提供全部的實現的 時候,這種情況就要使用繼承了。所以這麼看來繼承是對上面兩種功能的乙個黏合劑。

關於category的另外一些見解:

.        雖然category可以訪問類的例項變數,去不能建立新的例項變數,如果要創新的例項變數,請使用繼承;

.        在category中,不提倡對原有方法進行過載。原因非常簡單,在category中進行過載,無法對原方法進行訪問,而繼承中可以使用super。如果真的需要對原方法進行過載,請考慮繼承,比如我要定義乙個繼承自uiviewcontroller的類,就不能用category,因為,這我定義的這個類中,我要實現uiviewcontroller中的viewdidload、init等方法,用了category後父uiviewcontroller中的這些方法將無法被呼叫;

.        乙個類可以定義多個category,但是如果不同category中存在相同方法,編譯器會按編譯順序來判斷,哪個分類在最後編譯就會覆蓋掉,有同樣方法的父類和比這個分類先編譯的分類裡的同名方法。(所以說不是編器無法決定使用哪個,是使用最後編譯那個,因為其覆蓋了父類和先編譯的分類中的同名方法)

.        在定義category時,我們可以僅僅給出方法定義,而不需要給出具體的實現。這在程式增量開發時是非常有幫助的;

.        category是可以被繼承的。在某個父類中定義了category,那麼他所有的子類都具有該category;

.        在需要為某個類建立私有成員方法時,也用category的方式來實現。

category不能完全代替子類,有以下幾個最大的缺點:

.        當在category中覆蓋乙個繼承的方法,在category中的方法可以通過向super類傳送乙個訊息來呼叫被繼承的方法。但是,如果category中覆蓋的那個方法已經在這個類的其它category定義過了,則之前定義的方法將沒有機會被程式呼叫

.        在category中無法確定其能夠可靠的覆蓋某個方法,而這個方法已經在其它的category中定義過。這個問題在使用cocoa框架時尤其 突出。當你想覆蓋某個框架已經定義好的方法時,該方法已經在其它category中實現,這樣就無法確定哪個定義和實現會被最先使用,帶來很大的不確定 性。

.        如果你重新覆蓋定義了一些方法,往往會導致這個方法在整個框架中實現發生了變化。舉例來說,如果你增加了nsobject中 windowwillclose:的實現,這會導致所有的視窗呼叫那個新實現的方法,從而改變所有nswindows例項的行為。這會帶來很多不確定性, 並很有可能導致程式的崩潰。

34區分介面繼承和實現繼承

宣告 pure virtual 函式的目的是為了讓derived class 只繼承函式介面,具體實現須在derived class 中完成 宣告impure virtual 函式的目的是為了讓 derived class 繼承該函式的介面和預設實現,通過呼叫可在此預設實現基礎上新增新的 宣告non...

34區分介面繼承和實現繼承

函式介面繼承與函式實現繼承,在public繼承之下,derived classes總是繼承base class的介面。作為class的設計者 1.有時我們希望derived classes只繼承成員函式的介面 宣告 2.有時我們會希望derived classes同時繼承函式的介面與實現,但是又希望...

條款34 區分介面繼承和實現繼承

作為乙個 class 的設計者 1 有的時候你想要 derived classes 只繼承乙個 member function 的 inte ce declaration 宣告乙個 pure virtual function的目的是使 derived classes 繼承乙個函式 inte ce o...