第十章 范疇

范疇

范疇:

實(shí)現(xiàn)某個(gè)類的一部分方法的模塊叫作范疇或類別。

范疇和類一樣,都是在接口文件中聲明捷雕,在類文件中實(shí)現(xiàn)。但范疇中不能聲明實(shí)例變量壹甥,只能聲明方法救巷,聲明的方法既可以是類方法,也可以是實(shí)例方法句柠。

范疇的語法如下所示浦译。“類名”部分為范疇所屬的類的名字或即將添加該范疇的類的名字溯职【眩“類名”必須已經(jīng)存在的類,不能為一個(gè)不存在的類定義范疇:

//范疇的聲明

@interface類名(范疇名)

方法的聲明谜酒;

...

@end

//范疇的實(shí)現(xiàn)

@implementation類名(范疇名)

方法的定義叹俏;

...

@end

范疇和文件的組織:

包含主文件接口的頭文件中也包含了其他所有接口。

另外一種定義范疇的方法就是將每個(gè)范疇部分都單獨(dú)定義成一個(gè)頭文件僻族,每個(gè)實(shí)現(xiàn)文件都可以被單獨(dú)編譯粘驰。實(shí)現(xiàn)文件一般被命名為:“類名+范疇名.m”

范疇的接口部分需要遵循以下幾個(gè)原則:

范疇的接口部分必須引用主文件的接口文件

范疇的實(shí)現(xiàn)部分必須引用對(duì)應(yīng)的接口文件

使用范疇中的方法時(shí)必須引用這個(gè)方法所在的頭文件

作為子模塊的范疇:

上面講述的內(nèi)容的前提都是類的規(guī)模非常大,這種情況下通過使用范疇可以提高開發(fā)效率述么,但實(shí)際上規(guī)模大的類并不是一個(gè)好的選擇蝌数。在設(shè)計(jì)階段,如果發(fā)現(xiàn)一個(gè)類的方法非常多度秘,最好把這個(gè)類的功能分成幾個(gè)類來實(shí)現(xiàn)顶伞。

方法的前向聲明:

未在接口部分中聲明的局部方法,和未聲明的C語言函數(shù)一樣剑梳,其定義之前的代碼是沒法使用他們的唆貌。而通過使用范疇,就可以解決這個(gè)問題阻荒。類似于C語言中通過在文件的最前面加上函數(shù)聲明來解決類似的問題挠锥。

把局部方法都加入到一個(gè)局部的范疇中,并在實(shí)現(xiàn)文件的頭部加上范疇的聲明和定義侨赡。

將類劃分多個(gè)范疇之后蓖租,就必須考慮如何劃分共有方法。

如圖羊壹,劃分方法是創(chuàng)建一個(gè)對(duì)外不公開的接口文件蓖宦,其中聲明的類的共有變量和方法。像這樣油猫,即使在多個(gè)文件中進(jìn)行了共同的聲明稠茂,也可以定義僅供類內(nèi)文件使用而不對(duì)類外公開的方法和實(shí)例變量。這種方法叫私有方法。

為避免子類將父類的私有方法名覆蓋睬关,推薦為私有方法名加上固定前綴诱担。

類擴(kuò)展:

把類分為多個(gè)范疇來實(shí)現(xiàn)的情況下,主類和各個(gè)范疇都是獨(dú)立的电爹,每個(gè)范疇都不清楚其他的部分蔫仙。有的范疇可能是執(zhí)行前加載的,有的范疇可能是執(zhí)行時(shí)動(dòng)態(tài)加載的丐箩。這種實(shí)現(xiàn)方法的可擴(kuò)展性非常好摇邦,但編譯器在鏈接時(shí)不會(huì)檢查是否所有的范疇都被鏈接到了可執(zhí)行文件中。針對(duì)這種情況屎勘,引入了類擴(kuò)展的概念施籍。

類擴(kuò)展的聲明和范疇比較相似,只是圓括號(hào)之間沒有文本概漱。類擴(kuò)展中也可以增加實(shí)例變量:

@interface

Card () {

BOOLflag;

}

- (BOOL)hasSameSuit:(Card *)obj;

@end

類擴(kuò)展中聲明的方法需要在類的實(shí)現(xiàn)文件中實(shí)現(xiàn)丑慎,不管是否引入了類擴(kuò)展的定義,只要在類的實(shí)現(xiàn)部分中沒實(shí)現(xiàn)對(duì)應(yīng)的方法犀概,就會(huì)出現(xiàn)編譯錯(cuò)誤立哑。也就是說,通過將一定要實(shí)現(xiàn)的私有方法放入到類擴(kuò)展中姻灶,就可以防止忘記實(shí)現(xiàn)這個(gè)方法或漏掉方法的實(shí)現(xiàn)等問題铛绰。

但是,類擴(kuò)展自身并不會(huì)讓方法變?yōu)樗接蟹椒ú恚绻胱尫椒ㄗ兂伤接蟹椒ㄎ骊仨毑荒茏尠祟悢U(kuò)展的頭文件對(duì)外公開。

類擴(kuò)展中聲明的變量只能在引入了類的主接口和擴(kuò)展聲明的范疇中使用曾沈。主類的實(shí)現(xiàn)部分也可以聲明實(shí)例變量这嚣,但實(shí)例變量只在該文件(實(shí)現(xiàn)文件)中有效。與此相對(duì)塞俱,類擴(kuò)展中定義的實(shí)例變量可以在多個(gè)范疇中使用姐帚。

范疇和屬性聲明:

范疇的接口中可以包含屬性聲明,但范疇的實(shí)現(xiàn)部分不能包含@synthesize障涯。實(shí)現(xiàn)部分需手動(dòng)定義訪問方法罐旗。這是為了防止隨意訪問同一個(gè)類的不同文件中定義的實(shí)例變量。

類擴(kuò)展中也可以包含屬性聲明唯蝶,屬性是通過在類的實(shí)現(xiàn)部分包含@synthesize或者屬性方法來實(shí)現(xiàn)的九秀。類擴(kuò)展中也可以聲明實(shí)例變量的屬性。

類擴(kuò)展只能引用類內(nèi)的實(shí)例或方法粘我,至于范疇的頭文件是公開還是僅限類內(nèi)使用鼓蜒,則是由具體的使用情況決定的。

給現(xiàn)有類追加范疇

追加新的方法:

無論是自己定義的類還是系統(tǒng)的類,利用范疇都可以為已有類追加新方法都弹。

利用范疇只可以追加方法娇豫,不可以追加實(shí)例變量。

我們一般通過繼承的方式為現(xiàn)有類增加新的功能畅厢,但有時(shí)候使用子類并不方便锤躁,例如無法用通常的方法來為NSString創(chuàng)建子類等。而范疇的好處就是可以為正在使用的類增加新功能或详。

雖然范疇追加方法很方便,但也不要濫用郭计。

覆蓋已有方法:

新定義的范疇中的方法如果和原有方法重名的話霸琴,新定義的方法就會(huì)覆蓋老方法。但是不建議利用范疇覆蓋已有的方法昭伸。

關(guān)聯(lián)引用

關(guān)聯(lián)引用的概念:

通過范疇可以為一個(gè)類追加新的方法但不能追加實(shí)例變量梧乘。但是,利用Objective-C的動(dòng)態(tài)性庐杨,并借助運(yùn)行時(shí)(runtime)的功能选调,就可以為已存在的實(shí)例對(duì)象增加實(shí)例變量,這個(gè)功能叫做關(guān)聯(lián)引用(associative references)灵份。將這個(gè)功能和范疇組合在一起使用仁堪,即使不創(chuàng)建子類,也能夠?qū)︻愡M(jìn)行動(dòng)態(tài)擴(kuò)展填渠。

添加關(guān)聯(lián)和檢索關(guān)聯(lián):

這兩個(gè)方法定義在objc/runtime.h中弦聂。

voidobjc_setAssociatedObject(idobject,void*key,idvalue, objc_AssociationPolicy policy)

idobjc_getAssociatedObject(idobject,void*key)

在本章中,把要增加關(guān)聯(lián)的對(duì)象(想擴(kuò)展的對(duì)象)稱為所有者氛什,把追加的對(duì)象稱為引用對(duì)象莺葫。key的值必須使用確定的,不再改變的地址作為鍵值枪眉。使用地址作為key的原因是為了保證唯一性捺檬,key不會(huì)被用來存儲(chǔ)什么,也不會(huì)對(duì)其進(jìn)行賦值操作贸铜。

對(duì)象的存儲(chǔ)方法:

objc_setAssociatedObject的第四個(gè)參數(shù)policy是關(guān)聯(lián)策略堡纬。關(guān)聯(lián)策略表明了關(guān)聯(lián)對(duì)象是通過何種方式進(jìn)行關(guān)聯(lián)的,以及這種關(guān)聯(lián)是原子的還是非原子的萨脑。policy的值有以下幾種可供選擇隐轩,其中最常用的是OBJC_ASSOCIATION_RETAIN.

OBJC_ASSOCIATION_ASSIGN

基于引用計(jì)數(shù)的內(nèi)存管理時(shí),不會(huì)給關(guān)聯(lián)對(duì)象發(fā)送retain渤早,僅僅通過賦值進(jìn)行關(guān)聯(lián)职车。內(nèi)存管理使用垃圾回收時(shí),會(huì)把引用對(duì)象作為弱引用保存。

OBJC_ASSOCIATION_RETAIN_NONATOMIC

使用基于引用計(jì)數(shù)的內(nèi)存管理時(shí)悴灵,會(huì)給關(guān)聯(lián)對(duì)象發(fā)送retain消息并保持扛芽,如果同樣的key已經(jīng)關(guān)聯(lián)到其他對(duì)象,則會(huì)給其他對(duì)象發(fā)送release积瞒。釋放關(guān)聯(lián)對(duì)象的所有者時(shí)川尖,會(huì)給所有的關(guān)聯(lián)對(duì)象發(fā)送release消息。內(nèi)存使用垃圾回收時(shí)茫孔,會(huì)以強(qiáng)引用的形式保存關(guān)聯(lián)對(duì)象叮喳。

OBJC_ASSOCIATION_RETAIN

功能和上一個(gè)一樣,唯一的區(qū)別是OBJC_ASSOCIATION_RETAIN是多線程安全的缰贝,支持排他性關(guān)聯(lián)操作馍悟。

OBJC_ASSOCIATION_COPY_NONATOMIC

在進(jìn)行對(duì)象關(guān)聯(lián)的時(shí)候會(huì)復(fù)制一份原對(duì)象,并用新復(fù)制的對(duì)象進(jìn)行關(guān)聯(lián)操作剩晴。

OBJC_ASSOCIATION_COPY

功能和上一個(gè)一樣锣咒,唯一的區(qū)別是OBJC_ASSOCIATION_COPY時(shí)多線程安全的,支持排他性的關(guān)聯(lián)操作赞弥。

斷開關(guān)聯(lián):

voidobjc_removeAssociatedObjects(idobject)

通過范疇擴(kuò)展添加的實(shí)例變量并不是真正的實(shí)例變量毅整,所以對(duì)象復(fù)制和歸檔要特別注意。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绽左,一起剝皮案震驚了整個(gè)濱河市悼嫉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拼窥,老刑警劉巖承粤,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異闯团,居然都是意外死亡辛臊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門房交,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彻舰,“玉大人,你說我怎么就攤上這事候味∪谢剑” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵白群,是天一觀的道長(zhǎng)尚胞。 經(jīng)常有香客問我,道長(zhǎng)帜慢,這世上最難降的妖魔是什么笼裳? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任唯卖,我火速辦了婚禮,結(jié)果婚禮上躬柬,老公的妹妹穿的比我還像新娘拜轨。我一直安慰自己,他們只是感情好允青,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布橄碾。 她就那樣靜靜地躺著,像睡著了一般颠锉。 火紅的嫁衣襯著肌膚如雪法牲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天琼掠,我揣著相機(jī)與錄音皆串,去河邊找鬼。 笑死眉枕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的怜森。 我是一名探鬼主播速挑,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼副硅!你這毒婦竟也來了姥宝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤恐疲,失蹤者是張志新(化名)和其女友劉穎腊满,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體培己,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碳蛋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了省咨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肃弟。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖零蓉,靈堂內(nèi)的尸體忽然破棺而出笤受,到底是詐尸還是另有隱情,我是刑警寧澤敌蜂,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布箩兽,位于F島的核電站,受9級(jí)特大地震影響章喉,放射性物質(zhì)發(fā)生泄漏汗贫。R本人自食惡果不足惜身坐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芳绩。 院中可真熱鬧掀亥,春花似錦、人聲如沸妥色。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘹害。三九已至撮竿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笔呀,已是汗流浹背幢踏。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留许师,地道東北人房蝉。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像微渠,于是被迫代替她去往敵國(guó)和親搭幻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容