天天看點

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

通過分類(category)可以以子產品的方式向現有的類添加方法。

它提供了一種簡單的方式, 用它可以将類的定義子產品化到相關方法的組或分類中。它還提供了擴充現有類定義的簡便方式,并且不必通路類的源代碼,也無需建立子類。 

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

對于這段代碼來說,如何在不改變原來類模型的前提下,給person類擴充一些方法?

有2種方式

繼承,需要生成一個新類。

分類(category),這樣就不用使用繼承,不用生成新類,分類依賴于已經存在的類。開發中很常用。不用修改原來類的代碼。

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

在 xcode 裡,可以自動生成分類,不用手寫,建立 file,然後 oc-file, 分類選項即可。

好處

一個龐大的類可以分子產品開發

一個龐大的類可以由多個人來編寫,更有利于團隊合作

一般以子產品命名分類(當然使用作者命名也可以)

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

分類的作用:

在不改變原來類内容的基礎上,可以為類增加一些方法

使用注意:

 1.分類隻能增加方法,不能增加成員變量,如果實在想增加新的成員變量,那麼可以通過繼承實作。

 2.分類方法 實作 中 可以通路原來類中聲明的成員變量,否則增加的新方法就沒有意義了。

 3.分類可以重新實作原來類中的方法,但是會覆寫掉原來的方法,會導緻原來的方法沒法再使用(不建議覆寫)

 4.方法調用優先級:分類的方法 --> 原來類的方法  --> 父類的方法

優先去分類中查找,然後再去原來類中找,最後再去父類中找,如果有多個分類,且多個分類的裡面的方法都覆寫了原類方法,那麼調用順序和編譯順序有關。看編譯器先編譯哪個檔案,就先調用哪個檔案的覆寫的方法。

單擊—項目——出現build phases ——中的 compile source 中檢視:

編譯的檔案順序,順序可以人為改變。還發現,頭檔案是不被編譯的,這就再次驗證,頭檔案打醬油的特點,隻是為了程式設計規範,是以之前,不寫聲明,直接寫類的實作,不會報錯的原因就是這樣。

給系統自帶的類添加分類

實際開發中,常常給系統自帶的類添加分類,(系統自帶的類無法修改,但是可以添加分類增加方法)不一定隻是給自定義的類添加分類

這裡再次說明:分類的名稱,最好是按照子產品命名(或者功能命名),讓人一目了然。

給nsstring增加一個類方法:計算某個字元串中數字的個數,再增加一個對象方法:計算目前字元串中數字的個數

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

unichar 本質是:無符号短整型(有時候 char 類型當做 整數類型)

typedef unsigned short unichar;

在類方法裡,+ (int)numbercountofstring:(nsstring *)str;

我們可以不用寫那麼多代碼來實作,而是依靠對象方法來實作,直接return [str numbercount];即可!

再次注意

category可以通路原始類的執行個體變量,但不能添加變量,隻能添加方法。如果想添加變量,可以考慮通過繼承建立子類

category可以實作原始類的方法,但不推薦這麼做,因為它是直接替換掉原來的方法,這麼做的後果是再也不能通路原來的方法

多個category中如果實作了相同的方法,隻有最後一個參與編譯的才會有效

其實類也是一個對象,是class類型的對象,簡稱“類對象”,class類型的定義:

typedef struct objc_class *class;

類名就代表着類對象,每個類隻有一個類對象,即,記憶體中隻有一份類對象

+load 和 +initialize方法

+load方法:

在程式啟動的時候會加載所有的類和分類,并調用所有類和分類的+load方法。先加載父類,再加載子類。也就是先調用父類的+load方法,再調用子類的+load方法。先加載原始類,再加載原始類的分類 。不管程式運作過程有沒有用到這個類,都會調用+load加載 。

+initialize方法:

在第一次使用某個類時(比如建立對象等),就會調用一次+initialize方法,一個類隻會調用一次+initialize方法,先調用父類的,再調用子類的。先加載原類,再加載分類

description方法

-description方法

使用nslog和%@輸出某個對象時,會調用-description方法,并拿到傳回值進行輸出,沒有聲明在 nsobject 頭檔案。

+ description方法

使用nslog和%@輸出某個類時,會調用+description方法,并拿到傳回值進行輸出,在 nsobject 類的頭檔案裡

修改nslog的預設輸出

重寫-description或者+description方法即可

死循環陷阱

如果在-description方法中使用nslog列印self

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

每個類的方法清單都存儲在類對象中

每個方法都有一個與之對應的sel類型的資料

根據一個sel資料就可以找到方法的位址,進而調用方法

sel類型的定義

sel其實是對方法的一種包裝,将方法包裝成一個sel類型的資料,去找對應的方法位址。找到方法位址就可以調用方法,其實發送的消息就是sel

objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置
objective-c 文法快速過(5)oc 的分類-Category類的本質SEL資料類型方法的存儲位置

sel對象的建立

sel對象的其他用法

// 将sel對象轉為nsstring對象

person *p = [person new];

// 調用對象p的test方法

[p performselector:@selector(test)];

nslog輸出增強

__file__ :源代碼檔案名

__line__ :nslog代碼在第幾行

_cmd :代表着目前方法的sel

辛苦的勞動,轉載請注明出處,謝謝……

http://www.cnblogs.com/kubixuesheng/p/4314169.html

繼續閱讀