第四章 对象的类型和动态绑定
動(dòng)態(tài)綁定:程序在執(zhí)行時(shí)才確定對(duì)象的屬性和需要響應(yīng)的信息。
多態(tài):指同一操作作用于不同的類的實(shí)例時(shí),將產(chǎn)生不同的執(zhí)行結(jié)果。多態(tài)是面向?qū)ο蟮囊粋€(gè)重要的特征,大大增強(qiáng)了軟件的靈活性和擴(kuò)展性。
把類作為類型去聲明:NSObject *a; ?nil表空對(duì)象,即這個(gè)對(duì)象的指針指向空,值為0。
將對(duì)象作為參數(shù)傳遞的時(shí)候,傳遞的并不是對(duì)象本身,而是指向?qū)ο蟮闹羔槨?/p>
靜態(tài)類型:將一個(gè)變量聲明為特定類的對(duì)象,這種情況稱為靜態(tài)類型。使用靜態(tài)類型時(shí),編譯器可以在編譯時(shí)檢查接受者是否可以響應(yīng)收到的消息。
靜態(tài)類型檢查的總結(jié):
對(duì)于id類型的變量,調(diào)用任何方法都能夠通過(guò)編譯。
id類型的變量和被定義為特定類的變量之間是可以相互賦值的。
被定義為特定類對(duì)象的變量(靜態(tài)類型),如果調(diào)用了類或父類中未定義的方法,編譯器就會(huì)提出警告。
若是靜態(tài)類型的變量,子類類型的實(shí)例變量可以賦值給父類類型的實(shí)例變量。
若是靜態(tài)類型的變量,父類類型的實(shí)例變量不可以賦值給子類類型的實(shí)例變量。
若要判斷到底是哪個(gè)類的方法被執(zhí)行了,不要看變量所聲明的類型,而要看實(shí)際執(zhí)行時(shí)這個(gè)變量的類型。
id類型并不是(NSObject*)類型
編程中類型的定義:
[ obj msg ] 消息表達(dá)式
obj是消息接收者,是一個(gè)對(duì)象。 ? msg是消息。
消息名又稱為消息選擇器,選擇器,或方法。消息選擇器中并不包含參數(shù)和返回值的類型信息,消息選擇器和這些類型的信息結(jié)合在一起構(gòu)成簽名。簽名被用于在運(yùn)行時(shí)標(biāo)記一個(gè)方法,接口文件中方法的聲明也叫做簽名。
如果消息接受者和參數(shù)類型是運(yùn)行時(shí)確定的,那么消息簽名不唯一的話編譯就會(huì)出錯(cuò)。也就是說(shuō),objective-c中選擇器相同的消息,參數(shù)和返回值的類型也應(yīng)該相同。
類的前置聲明:
當(dāng)定義一個(gè)類的時(shí)候,有時(shí)會(huì)將類的實(shí)例變量,類方法的參數(shù)和返回值的類型來(lái)指定另一個(gè)類。這種情況有兩種方法實(shí)現(xiàn)定義:
1.在新定義的類的接口文件中引入原有類的頭文件。(該方法的缺點(diǎn)是頭文件中除了類名還有其他信息的定義,此外還可能引入其他頭文件,增加了編譯時(shí)的負(fù)擔(dān)如果僅僅是在類型定義的時(shí)候使用一下類名,則使用方法2來(lái)解決)
2.@class + 類名+”;",class指令后可以一次接多個(gè)類,中間用逗號(hào)隔開。該方法叫做類的前置聲明。(@class可以提升程序的整體編譯速度,而且當(dāng)多個(gè)接口出現(xiàn)類的嵌套定義時(shí)如果只是包含對(duì)方的頭文件無(wú)法解決,通過(guò)類的前置聲明可以解決。但要注意的是,如果新定義的類要使用原有類的具體成員或方法,就一定要引入原有類的頭文件)
強(qiáng)制類型轉(zhuǎn)換:?
有些情況下必須使用強(qiáng)制類型轉(zhuǎn)換,一個(gè)典型的例子就是父類類型的指針實(shí)際上指向了子類的變量。
(除了id之外,指針變量只能調(diào)用編譯時(shí)類型的方法,不能調(diào)用它運(yùn)行時(shí)的類型方法,故強(qiáng)轉(zhuǎn))
雖然強(qiáng)制轉(zhuǎn)換的功能很強(qiáng)大,但會(huì)讓編譯器的類型檢查變得沒(méi)有意義,所以盡量少用。不得不用時(shí),要重新思考設(shè)計(jì)是否合理。
實(shí)例變量的訪問(wèn)權(quán)限:
只能訪問(wèn)靜態(tài)類型定義的實(shí)例對(duì)象的內(nèi)部變量。因?yàn)槟芊裨L問(wèn)實(shí)例對(duì)象的內(nèi)部變量是需要經(jīng)過(guò)檢查的,該檢查在編譯期完成。
訪問(wèn)器:
OC不允許直接從外部訪問(wèn)和修改實(shí)例對(duì)象的屬性,而僅僅可以訪問(wèn)同一個(gè)類的其他實(shí)例對(duì)象的變量,需要定義專門的方法來(lái)訪問(wèn)或修改實(shí)例變量:
getter方法(讀取):從外部訪問(wèn)這個(gè)屬性的方法應(yīng)和屬性同名。
setter方法(修改):定義修改該屬性的方法時(shí),用set做前綴,之后接要更改的屬性的名稱,屬性名的首字母大寫。
雖然子類的方法可以直接訪問(wèn)父類的實(shí)例變量,但我們要養(yǎng)成一個(gè)好的習(xí)慣,即盡量使用getter/setter 方法來(lái)訪問(wèn)父類中的實(shí)例變量,這樣可以使程序做到盡可能的低耦合。
為什么不允許直接訪問(wèn)成員屬性?一切都是為了封裝,使程序盡可能地低耦合。
實(shí)例變量的可見性:
@private:只能在聲明它的類內(nèi)訪問(wèn),子類不可以訪問(wèn)??梢栽诜椒ㄖ型ㄟ^(guò)->來(lái)訪問(wèn)同一個(gè)類的實(shí)例變量。
@protected:能夠被聲明它的類和任何子類訪問(wèn)。類方法中可以通過(guò)->來(lái)訪問(wèn)本類實(shí)例對(duì)象的實(shí)例變量。沒(méi)有顯式指定可見性的實(shí)例變量都是此屬性。
@package:類所在的框架內(nèi)可以像@public一樣訪問(wèn)。而框架外則同@private一樣,不允許訪問(wèn)。
@public:作用范圍最大,本類和其他類都可以直接訪問(wèn)。
在實(shí)現(xiàn)部分中定義實(shí)例變量:
采用這種方法后,子類無(wú)法訪問(wèn)父類的實(shí)例變量。在實(shí)現(xiàn)文件中定義的實(shí)例變量的可見性默認(rèn)是@private,也可用@public等來(lái)重設(shè)可見性。
所以讓一個(gè)變量對(duì)外不可見有兩種方法,一種是把變量的可見屬性設(shè)為@private,另一種就是把變量定義在實(shí)現(xiàn)文件中。
類對(duì)象:
在OC中,對(duì)類的定義分為兩部分,一部分定義所生成的實(shí)例的類型,另外一部分定義類自身的行為。
類本身也作為一個(gè)對(duì)象存在。類對(duì)象有自己的方法和變量,分別被稱為類方法和類變量,在OC中,只有類方法的概念,沒(méi)有類變量。至今為止我們一直把類的實(shí)例變量和方法稱為實(shí)例變量和實(shí)例方法,這樣可以和類變量和類方法進(jìn)行區(qū)分。OC中類對(duì)象也被稱為factory,類方法稱為factory method。類對(duì)象是在程序運(yùn)行時(shí)自動(dòng)生成的。每個(gè)類只有一個(gè)類對(duì)象,不需要手動(dòng)生成。類方法可以訪問(wèn)類對(duì)象管理的變量。
類對(duì)象的類型:
類對(duì)象可以用id類型來(lái)表示,也可以用OC為其專門定義的Class類型來(lái)表示。NSObject中定義了類方法class,所有類都可以用這個(gè)方法來(lái)獲取類對(duì)象。除此之外,NSObject中還定義了實(shí)例方法class,所有的實(shí)例對(duì)象都可以使用class實(shí)例方法,這個(gè)方法返回的是對(duì)象所屬類的類對(duì)象。
類名的使用:
將類名定義為消息接受者是類對(duì)象特有的功能,除此之外類名只能在類型定義時(shí)使用。
類方法的定義:
實(shí)例方法以“-”開頭,類方法以“+”開頭。類方法的一個(gè)典型操作就是創(chuàng)建類的實(shí)例對(duì)象,類對(duì)象收到alloc這種消息之后就會(huì)生成類的實(shí)例。繼承情況下,子類可以訪問(wèn)父類的類方法。類方法不能訪問(wèn)類中定義的實(shí)例變量和實(shí)例方法。因?yàn)轭悓?duì)象只有一個(gè),而類的實(shí)例對(duì)象有任意個(gè),所以如果類對(duì)象可以訪問(wèn)實(shí)例變量,就會(huì)不清楚到底訪問(wèn)的是哪一個(gè)實(shí)例對(duì)象的變量。
其次,類方法執(zhí)行時(shí)用self代表了類對(duì)象自身。
alloc是類方法,dealloc是實(shí)例方法。
類變量:
OC不支持類變量。OC通過(guò)在實(shí)現(xiàn)文件中定義靜態(tài)變量的方法來(lái)代替類變量。繼承情況下,可以通過(guò)定義類方法(getter,setter)來(lái)進(jìn)行訪問(wèn)父類中定義的變量。
類對(duì)象的初始化:
OC的根類NSObject中存在一個(gè)initialize類方法,可以使用這個(gè)方法對(duì)各類對(duì)象進(jìn)行初始化。每個(gè)類接收到消息之前,為這個(gè)類調(diào)用一次initialize,調(diào)用之前先調(diào)用父類的initialize方法。如果子類中沒(méi)有實(shí)現(xiàn)initialize方法,其父類的initialize方法就會(huì)被調(diào)用兩次,面向自己一次,面向子類一次。
初始化方法的返回值:
之所以將返回值類型定義為id,是因?yàn)榭紤]到初始化方法的返回值不是具體的類的類型,而是可變的,取決于上下文。例如父類初始化返回值定義為Volume*,則其子類調(diào)用父類初始化方法時(shí)返回的也是Volume。所以應(yīng)將其定義為id。
總結(jié)
以上是生活随笔為你收集整理的第四章 对象的类型和动态绑定的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 总结
- 下一篇: MySQL mysqldump命令