Cocoa對(duì)象 根類(lèi)是本文要介紹的內(nèi)容,僅憑Objective-C語(yǔ)言和運(yùn)行環(huán)境并不足以構(gòu)造哪怕是最簡(jiǎn)單的面向?qū)ο蟮某绦?,至少是不容易的。還缺少一些東西:即所有對(duì)象公有的基本行為和接口的定義。根類(lèi)正是提供了這些定義。 之所以叫根類(lèi),是因?yàn)樗挥谡麄€(gè)類(lèi)層次(這里是指Cocoa的類(lèi)層次)的根上。根類(lèi)不從其它類(lèi)繼承,但是類(lèi)層次中的所有其它類(lèi)都最終從根類(lèi)繼承下來(lái)。根類(lèi)連同Objective-C語(yǔ)言,是Cocoa直接訪問(wèn)Objective-C運(yùn)行環(huán)境或與之交互的基本途徑。Cocoa對(duì)象的大部分對(duì)象行為能力都是從根類(lèi)得到的。 Cocoa提供了兩個(gè)根類(lèi):NSObject和NSProxy。Cocoa將后者定義為抽象類(lèi),用于表示其它對(duì)象的替身對(duì)象。因此NSProxy類(lèi)在分布式對(duì)象架構(gòu)中是很重要的。由于作用比較特別,NSProxy在Cocoa程序中出現(xiàn)頻率很低。Cocoa開(kāi)發(fā)者在提到根類(lèi)時(shí),幾乎總是指NSObject。 本部分將討論NSObject類(lèi),看看它如何與運(yùn)行環(huán)境進(jìn)行交互,以及它為所有Cocoa對(duì)象定義的基本行為和接口。其中主要是它為對(duì)象的內(nèi)存分配、初始化、內(nèi)存管理、內(nèi)省、以及運(yùn)行環(huán)境支持所聲明的方法。這些概念是理解Cocoa的基礎(chǔ)。 NSObject NSObject是大多數(shù)Objective-C類(lèi)層次的根類(lèi),它沒(méi)有超類(lèi)。其它類(lèi)從NSObject繼承訪問(wèn)Objective-C語(yǔ)言運(yùn)行時(shí)系統(tǒng)的基本接口,它們的實(shí)例可以得到對(duì)象行為的能力。 雖然NSObject不是一個(gè)嚴(yán)格的抽象類(lèi),但它是個(gè)虛類(lèi)。僅憑一個(gè)NSObject實(shí)例除了作為一個(gè)簡(jiǎn)單的對(duì)象外,不能完成任何有用的工作。為了在您的程序中加入特有的屬性和邏輯,必須創(chuàng)建一個(gè)或多個(gè)從NSObject或其派生類(lèi)繼承下來(lái)的類(lèi)。 NSObject采納了NSObject協(xié)議(參見(jiàn)"根類(lèi)—和協(xié)議"部分)。NSObject協(xié)議支持多個(gè)根對(duì)象。舉例來(lái)說(shuō),NSProxy是另一個(gè)根類(lèi),它不是繼承自NSObject,但采納了NSObject協(xié)議,以便和其它Objective-C對(duì)象共用一個(gè)公共的接口。 NSObject和java.lang.Object一起,是Java版本的Cocoa中所有類(lèi)的根類(lèi),包括Foundation和Application Kit。 根類(lèi)—和協(xié)議 NSObject不僅僅是一個(gè)類(lèi)的名稱,還是一個(gè)協(xié)議的名稱。兩者對(duì)于定義一個(gè)Cocoa對(duì)象都是必要的。NSObject協(xié)議指定了Cocoa中所有根類(lèi)必須的基本編程接口,因此不僅NSObject類(lèi)采納了這個(gè)同名的協(xié)議,其它根類(lèi)也采納這個(gè)協(xié)議,比如NSProxy。NSObject類(lèi)進(jìn)一步指定了不作為代理對(duì)象的Cocoa對(duì)象的基本編程接口。 NSObject及類(lèi)似的協(xié)議用于Cocoa對(duì)象的總體定義(而不是在類(lèi)接口中包含那些協(xié)議),使多個(gè)根類(lèi)成為可能。每個(gè)根類(lèi)共用一個(gè)由它們采納的協(xié)議定義的公共接口。 在另一種意義上,NSObject不僅僅是個(gè)“根”協(xié)議。雖然NSObject類(lèi)沒(méi)有正式采納NSCopying、NSMutableCopying、和NSCoding協(xié)議,但它聲明和實(shí)現(xiàn)了與那些協(xié)議相關(guān)的方法(而且,包含NSObject類(lèi)的NSObject.h頭文件中也包含上面提到的所有四個(gè)協(xié)議的定義)。對(duì)象拷貝、編碼、和解碼是對(duì)象行為的基本部分。很多子類(lèi)(如果不是絕大多數(shù)的話)都希望采納和遵循這些協(xié)議。 請(qǐng)注意:其它Cocoa類(lèi)可以(而且確實(shí)是)通過(guò)范疇將方法添加到NSObject中。這些范疇通常是一些非正式的協(xié)議,在委托中使用。它們?cè)试S委托對(duì)象選擇實(shí)現(xiàn)范疇中的部分方法。然而,NSObject的范疇并不被認(rèn)為是基本對(duì)象接口的一部分。 根類(lèi)方法概述 NSObject根類(lèi)和它采納的NSObject協(xié)議及其它“根” 協(xié)議一起,為所有不作為代理對(duì)象的Cocoa對(duì)象指定了如下的接口和行為特征: 分配、初始化、和復(fù)制。NSObject類(lèi)中的一些方法(包括一些來(lái)自協(xié)議的方法)用于對(duì)象的創(chuàng)建、初始化、和復(fù)制: alloc和allocWithZone:方法用于從某內(nèi)存區(qū)域中分配一個(gè)對(duì)象內(nèi)存,并使對(duì)象指向其運(yùn)行時(shí)的類(lèi)定義。 init方法是對(duì)象初始化原型,負(fù)責(zé)將對(duì)象的實(shí)例變量設(shè)置為一個(gè)已知的初始狀態(tài)。initialize和load是兩個(gè)類(lèi)方法,它們讓對(duì)象有機(jī)會(huì)對(duì)自身進(jìn)行初始化。 new是一個(gè)將簡(jiǎn)單的內(nèi)存分配和初始化結(jié)合起來(lái)的便利方法。 copy和copyWithZone:方法用于拷貝實(shí)現(xiàn)這些(由NSCopying協(xié)議定義的)方法的類(lèi)的實(shí)例。希望支持可變對(duì)象拷貝的類(lèi)則需要實(shí)現(xiàn)mutableCopy和mutableCopyWithZone:(由NSMutableCopying協(xié)議定義)方法。 更多信息請(qǐng)參見(jiàn) "對(duì)象的創(chuàng)建"部分。 對(duì)象的保持和清理。下面的方法對(duì)面向?qū)ο蟪绦虻膬?nèi)存管理特別重要: retain方法增加對(duì)象的保持次數(shù)。 release方法減少對(duì)象的保持次數(shù)。 autorelease方法也是減少對(duì)象的保持次數(shù),但是以推遲的方式。 retainCount方法返回對(duì)當(dāng)前的保持次數(shù)。 dealloc方法由需要釋放對(duì)象的實(shí)例變量以及釋放動(dòng)態(tài)分配的內(nèi)存的類(lèi)實(shí)現(xiàn)。 更多信息請(qǐng)參見(jiàn) Cocoa對(duì)象的生命周期 內(nèi)省和比較。NSObjec有很多方法可以查詢對(duì)象的運(yùn)行時(shí)信息。這些內(nèi)省方法有助于找出對(duì)象在類(lèi)層次中的位置,確定對(duì)象是否實(shí)現(xiàn)特定的方法,以及測(cè)試對(duì)象是否遵循某種協(xié)議。這些方法中的一部分僅實(shí)現(xiàn)為類(lèi)方法。 superclass和class方法(實(shí)現(xiàn)為類(lèi)和實(shí)例方法)分別以Class對(duì)象的形式返回接收者的超類(lèi)和類(lèi)。 您可以通過(guò)isKindOfClass:和isMemberOfClass:方法來(lái)確定對(duì)象屬于哪個(gè)類(lèi)。后者用于測(cè)試接收者是否為指定類(lèi)的實(shí)例。isSubclassOfClass:類(lèi)方法則用于測(cè)試類(lèi)的繼承性。 respondsToSelector:方法用于測(cè)試接收者是否實(shí)現(xiàn)由選擇器參數(shù)標(biāo)識(shí)的方法。instancesRespondToSelector:類(lèi)方法則用于測(cè)試給定類(lèi)的實(shí)例是否實(shí)現(xiàn)指定的方法。 conformsToProtocol:方法用于測(cè)試接收者(對(duì)象或類(lèi))是否遵循給定的協(xié)議。 isEqual:和hash方法用于對(duì)象的比較。 description方法允許對(duì)象返回一個(gè)內(nèi)容描述字符串;這個(gè)方法的輸出經(jīng)常用于調(diào)試(“print object”命令),以及在格式化字符串中和“%@”指示符一起表示對(duì)象。 更多信息請(qǐng)參見(jiàn) 內(nèi)省 。 對(duì)象的編碼和解碼。下面的方法和對(duì)象的編解碼(作為歸檔過(guò)程的一部分)有關(guān): encodeWithCoder:和initWithCoder:是NSCoding協(xié)議僅有的方法。前者使對(duì)象可以對(duì)其實(shí)例變量進(jìn)行編碼,后者則使對(duì)象可以根據(jù)解碼過(guò)的實(shí)例變量對(duì)自身進(jìn)行初始化。 NSObject類(lèi)中聲明了一些于對(duì)象編碼有關(guān)的方法:classForCoder:、replacementObjectForCoder:、和awakeAfterUsingCoder:。 進(jìn)一步信息請(qǐng)參見(jiàn)Cocoa的歸檔和序列化編程指南一文。 消息的轉(zhuǎn)發(fā)。forwardInvocation:和相關(guān)的方法允許一個(gè)對(duì)象將消息轉(zhuǎn)發(fā)給另一個(gè)對(duì)象。 消息的派發(fā)。以performSelector...開(kāi)頭的一組方法使您可以在指定的延遲后派發(fā)消息,以及將消息從輔助線程派發(fā)(同步或異步)到主線程。 NSObject還有幾個(gè)其它的方法,包括一些處理版本和姿態(tài)(后者使一個(gè)類(lèi)在運(yùn)行時(shí)將自己表示為另一個(gè)類(lèi))的類(lèi)方法,以及一些訪問(wèn)運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)的方法,比如方法選擇器和指向方法實(shí)現(xiàn)的函數(shù)指針。 接口規(guī)范 某些NSObject方法只是為了被調(diào)用,而另一些方法則是為了被重載。舉例來(lái)說(shuō),大多數(shù)子類(lèi)不應(yīng)該重載allocWithZone:方法,但必須實(shí)現(xiàn)init方法—至少需要實(shí)現(xiàn)一個(gè)最終調(diào)用根類(lèi)的init方法(請(qǐng)參見(jiàn)"對(duì)象的創(chuàng)建"部分)的初始化方法。對(duì)于那些期望子類(lèi)重載的方法,NSObject的實(shí)現(xiàn)或者什么也不做,或者返回一個(gè)合理的值,比如self。這些缺省實(shí)現(xiàn)使我們有可能向任意的Cocoa對(duì)象—甚至是沒(méi)有重載這些方法的對(duì)象—發(fā)送諸如init這樣得基本消息,而又不必冒運(yùn)行時(shí)例外的風(fēng)險(xiǎn)。在發(fā)送消息之前,不必進(jìn)行檢查(通過(guò)respondsToSelector:方法)。更加重要的是,NSObject的這些“占位”方法為Cocoa對(duì)象定義了一個(gè)公共的結(jié)構(gòu),并建立了一些規(guī)則,如果所有的對(duì)象都遵循這些規(guī)則,對(duì)象間的交互將更加可靠。 實(shí)例方法和類(lèi)方法 運(yùn)行環(huán)境系統(tǒng)以一種特殊的方式處理根類(lèi)定義的方法。根類(lèi)定義的實(shí)例方法可以由實(shí)例對(duì)象和類(lèi)對(duì)象執(zhí)行,因此所有類(lèi)對(duì)象都可以訪問(wèn)根類(lèi)定義的實(shí)例方法。對(duì)于任何類(lèi)對(duì)象,如果對(duì)象中不包含同名的類(lèi)方法,就可以執(zhí)行根類(lèi)的所有實(shí)例方法。 舉例來(lái)說(shuō),一個(gè)類(lèi)對(duì)象可以通過(guò)發(fā)送消息來(lái)執(zhí)行NSObject的respondsToSelector:和performSelector:withObject:實(shí)例方法:
請(qǐng)注意,只有根類(lèi)中定義的實(shí)例方法才可以在類(lèi)對(duì)象中使用。在上面的例子中,如果MyClass重新實(shí)現(xiàn)了respondsToSelector:或者performSelector:withObject:方法,則那些新的版本將只能用于實(shí)例對(duì)象。MyClass的類(lèi)對(duì)象只能執(zhí)行NSObject類(lèi)定義的版本(當(dāng)然,如果MyClass將respondsToSelector:或performSelector:withObject: 實(shí)現(xiàn)為類(lèi)方法,而不是實(shí)例方法,則該類(lèi)對(duì)象可以執(zhí)行這些新的實(shí)現(xiàn))。 小結(jié):Cocoa對(duì)象 根類(lèi)的內(nèi)容介紹完了,希望本文對(duì)你 有所幫助! 【編輯推薦】 【責(zé)任編輯:李程站 TEL:(010)68476606】 點(diǎn)贊 0 |
|