動(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)用任何方法都能夠通過編譯冯勉。
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ò)车遂。也就是說,objective-c中選擇器相同的消息斯辰,參數(shù)和返回值的類型也應(yīng)該相同舶担。
類的前置聲明:
當(dāng)定義一個(gè)類的時(shí)候,有時(shí)會(huì)將類的實(shí)例變量彬呻,類方法的參數(shù)和返回值的類型來指定另一個(gè)類衣陶。這種情況有兩種方法實(shí)現(xiàn)定義:
1.在新定義的類的接口文件中引入原有類的頭文件。(該方法的缺點(diǎn)是頭文件中除了類名還有其他信息的定義闸氮,此外還可能引入其他頭文件剪况,增加了編譯時(shí)的負(fù)擔(dān)如果僅僅是在類型定義的時(shí)候使用一下類名,則使用方法2來解決)
2.@class + 類名+”;"蒲跨,class指令后可以一次接多個(gè)類译断,中間用逗號(hào)隔開。該方法叫做類的前置聲明财骨。(@class可以提升程序的整體編譯速度镐作,而且當(dāng)多個(gè)接口出現(xiàn)類的嵌套定義時(shí)如果只是包含對(duì)方的頭文件無法解決,通過類的前置聲明可以解決隆箩。但要注意的是该贾,如果新定義的類要使用原有類的具體成員或方法,就一定要引入原有類的頭文件)
強(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ì)讓編譯器的類型檢查變得沒有意義糠爬,所以盡量少用寇荧。不得不用時(shí),要重新思考設(shè)計(jì)是否合理执隧。
實(shí)例變量的訪問權(quán)限:
只能訪問靜態(tài)類型定義的實(shí)例對(duì)象的內(nèi)部變量揩抡。因?yàn)槟芊裨L問實(shí)例對(duì)象的內(nèi)部變量是需要經(jīng)過檢查的户侥,該檢查在編譯期完成。
訪問器:
OC不允許直接從外部訪問和修改實(shí)例對(duì)象的屬性峦嗤,而僅僅可以訪問同一個(gè)類的其他實(shí)例對(duì)象的變量蕊唐,需要定義專門的方法來訪問或修改實(shí)例變量:
getter方法(讀取):從外部訪問這個(gè)屬性的方法應(yīng)和屬性同名烁设。
setter方法(修改):定義修改該屬性的方法時(shí)替梨,用set做前綴,之后接要更改的屬性的名稱装黑,屬性名的首字母大寫副瀑。
雖然子類的方法可以直接訪問父類的實(shí)例變量,但我們要養(yǎng)成一個(gè)好的習(xí)慣曹体,即盡量使用getter/setter 方法來訪問父類中的實(shí)例變量俗扇,這樣可以使程序做到盡可能的低耦合硝烂。
為什么不允許直接訪問成員屬性箕别?一切都是為了封裝,使程序盡可能地低耦合滞谢。
實(shí)例變量的可見性:
@private:只能在聲明它的類內(nèi)訪問串稀,子類不可以訪問∈ㄑ睿可以在方法中通過->來訪問同一個(gè)類的實(shí)例變量母截。
@protected:能夠被聲明它的類和任何子類訪問。類方法中可以通過->來訪問本類實(shí)例對(duì)象的實(shí)例變量橄教。沒有顯式指定可見性的實(shí)例變量都是此屬性清寇。
@package:類所在的框架內(nèi)可以像@public一樣訪問。而框架外則同@private一樣护蝶,不允許訪問华烟。
@public:作用范圍最大,本類和其他類都可以直接訪問持灰。
在實(shí)現(xiàn)部分中定義實(shí)例變量:
采用這種方法后盔夜,子類無法訪問父類的實(shí)例變量。在實(shí)現(xiàn)文件中定義的實(shí)例變量的可見性默認(rèn)是@private堤魁,也可用@public等來重設(shè)可見性喂链。
所以讓一個(gè)變量對(duì)外不可見有兩種方法,一種是把變量的可見屬性設(shè)為@private妥泉,另一種就是把變量定義在實(shí)現(xiàn)文件中椭微。
類對(duì)象:
在OC中,對(duì)類的定義分為兩部分盲链,一部分定義所生成的實(shí)例的類型蝇率,另外一部分定義類自身的行為检诗。
類本身也作為一個(gè)對(duì)象存在。類對(duì)象有自己的方法和變量瓢剿,分別被稱為類方法和類變量逢慌,在OC中,只有類方法的概念间狂,沒有類變量攻泼。至今為止我們一直把類的實(shí)例變量和方法稱為實(shí)例變量和實(shí)例方法,這樣可以和類變量和類方法進(jìn)行區(qū)分鉴象。OC中類對(duì)象也被稱為factory忙菠,類方法稱為factory method。類對(duì)象是在程序運(yùn)行時(shí)自動(dòng)生成的纺弊。每個(gè)類只有一個(gè)類對(duì)象牛欢,不需要手動(dòng)生成。類方法可以訪問類對(duì)象管理的變量淆游。
類對(duì)象的類型:
類對(duì)象可以用id類型來表示傍睹,也可以用OC為其專門定義的Class類型來表示。NSObject中定義了類方法class犹菱,所有類都可以用這個(gè)方法來獲取類對(duì)象拾稳。除此之外,NSObject中還定義了實(shí)例方法class腊脱,所有的實(shí)例對(duì)象都可以使用class實(shí)例方法访得,這個(gè)方法返回的是對(duì)象所屬類的類對(duì)象。
類名的使用:
將類名定義為消息接受者是類對(duì)象特有的功能陕凹,除此之外類名只能在類型定義時(shí)使用悍抑。
類方法的定義:
實(shí)例方法以“-”開頭,類方法以“+”開頭杜耙。類方法的一個(gè)典型操作就是創(chuàng)建類的實(shí)例對(duì)象搜骡,類對(duì)象收到alloc這種消息之后就會(huì)生成類的實(shí)例。繼承情況下泥技,子類可以訪問父類的類方法浆兰。類方法不能訪問類中定義的實(shí)例變量和實(shí)例方法。因?yàn)轭悓?duì)象只有一個(gè)珊豹,而類的實(shí)例對(duì)象有任意個(gè)簸呈,所以如果類對(duì)象可以訪問實(shí)例變量,就會(huì)不清楚到底訪問的是哪一個(gè)實(shí)例對(duì)象的變量店茶。
其次蜕便,類方法執(zhí)行時(shí)用self代表了類對(duì)象自身。
alloc是類方法贩幻,dealloc是實(shí)例方法轿腺。
類變量:
OC不支持類變量两嘴。OC通過在實(shí)現(xiàn)文件中定義靜態(tài)變量的方法來代替類變量。繼承情況下族壳,可以通過定義類方法(getter憔辫,setter)來進(jìn)行訪問父類中定義的變量。
類對(duì)象的初始化:
OC的根類NSObject中存在一個(gè)initialize類方法仿荆,可以使用這個(gè)方法對(duì)各類對(duì)象進(jìn)行初始化贰您。每個(gè)類接收到消息之前,為這個(gè)類調(diào)用一次initialize拢操,調(diào)用之前先調(diào)用父類的initialize方法锦亦。如果子類中沒有實(shí)現(xiàn)initialize方法,其父類的initialize方法就會(huì)被調(diào)用兩次令境,面向自己一次杠园,面向子類一次。
初始化方法的返回值:
之所以將返回值類型定義為id舔庶,是因?yàn)榭紤]到初始化方法的返回值不是具體的類的類型抛蚁,而是可變的,取決于上下文栖茉。例如父類初始化返回值定義為Volume*篮绿,則其子類調(diào)用父類初始化方法時(shí)返回的也是Volume。所以應(yīng)將其定義為id吕漂。