object c中的多态
2,多態(tài)的優(yōu)勢:不同的類對象可以使用習(xí)慣的調(diào)用方式;簡化了編程接口;實(shí)現(xiàn)類和實(shí)例的接口隔離。
動(dòng)態(tài)綁定,多態(tài),在C++中主要是指基類指針,調(diào)用繼承類所實(shí)現(xiàn)的虛方法。
在object C中, 有比較新的展現(xiàn)形式。
(一)消息機(jī)制
oc中的消息機(jī)制就是 一個(gè)動(dòng)態(tài)綁定的過程,
? ? ? ? ? ?每個(gè)類實(shí)例的第一個(gè)字段isa指針,指向類的結(jié)構(gòu)體定義,里面有函數(shù)列表,緩存函數(shù)列表,協(xié)議列表,類名,實(shí)例參數(shù)列表,實(shí)例大小.....。
? ? ? ? ? ?消息調(diào)用過程:編譯過程中會(huì)在函數(shù)調(diào)用的代碼處添加, obj_msgSend: 函數(shù)調(diào)用;程序運(yùn)行期,此函數(shù)完成動(dòng)態(tài)綁定的所有過程。按照編譯期改為 obj_msgSend 寫時(shí),填入的調(diào)用類,被調(diào)用者類,和他們的函數(shù)列表,找到對應(yīng)的IMP即函數(shù)指針,完成函數(shù)調(diào)用。
???????????objc_msgSend(receiver, selector, arg1, arg2, ...)
該消息函數(shù)做了動(dòng)態(tài)綁定所需要的一切:
-
它首先找到選標(biāo)所對應(yīng)的方法實(shí)現(xiàn)。因?yàn)椴煌念悓ν环椒赡軙?huì)有不同的實(shí)現(xiàn),所以找到的方法實(shí)現(xiàn)依賴于消息接收者的類型。
-
然后將消息接收者對象(指向消息接收者對象的指針)以及方法中指定的參數(shù)傳給找到的方法實(shí)現(xiàn)。
-
最后,將方法實(shí)現(xiàn)的返回值作為該函數(shù)的返回值返回。
(二)delegate,protocol配合的觀察者模式,是oc中多態(tài)的最常見運(yùn)用方式
觀察者注冊,符合某種protocol的id實(shí)例指針,
當(dāng)被觀察者認(rèn)為條件滿足是,通過實(shí)例指針id,去調(diào)用protocol規(guī)定的同一種方法即可。
不論多少個(gè)觀察者,只要都實(shí)現(xiàn)了protocol規(guī)定的方法,都可以完成調(diào)用,
Object-C難以理解的一些概念
1.object-c 怎么實(shí)現(xiàn)多態(tài)
答:多態(tài)是在runtime里面實(shí)現(xiàn)的,在編譯的時(shí)候,compiler把所有class的定義都存放在class 實(shí)例對象里面,class實(shí)例對象包含了class的父class 實(shí)例對象的地址,class方法的select id和地址, class變量的偏移等。所有new出來的object都是從NSObject繼承過來的,所以所有對象都自動(dòng)包含了一個(gè)isa的指針,這個(gè)指針在調(diào)用alloc為object分配地址的時(shí)候被指向class對象的地址,在運(yùn)行的時(shí)候,我們調(diào)用class 方法是通過給object發(fā)送消息
[myobj method]這樣的形式,但編譯器會(huì)把這句話替換成
id objc_msgSend(id theReceiver, SEL theSelector, ...)
第一個(gè)參數(shù)就是myobj,第二個(gè)參數(shù)是“method”這個(gè)字符串經(jīng)過編碼以后得到的唯一值,apple在runtime的時(shí)候查找method都是用
selector來做的,這樣效率會(huì)比字符串比較的效率要高。
objc_msgSend這個(gè)函數(shù)的執(zhí)行過程大概就是,從thereceiver(也就是myobj)里面得到isa的地址,這個(gè)地址指向前面講到的
編譯器生成的class的object實(shí)例的地址(具體的結(jié)構(gòu)請參考The Objective-C Programming Language),然后比較方法的selector
如果找到了,就知道了method的地址,就直接調(diào)用了。
2.對象的method是怎么訪問對象 變量的?
答:在編譯期間,編譯器可以知道指定class的所有繼承關(guān)系,所以它也知道要生成的object包含的所有變量(包含了父類的)。這樣
它就能算出所有變量相對于oject的首地址的偏移。在運(yùn)行的時(shí)候,我們這樣調(diào)用object 的方法:
[myobj method];
實(shí)際上編譯器會(huì)隱含的把myobj的地址傳遞給method,所謂第一個(gè)參數(shù)(這個(gè)就是隱含參數(shù)的概念,請參考apple object c的文檔)
這樣知道了object的首地址和變量的偏移,也就知道了變量的地址。
3。self和super關(guān)鍵字是怎么實(shí)現(xiàn)的?
答:這個(gè)是面對對象語言容易出錯(cuò)的地方,必須要理解這兩個(gè)關(guān)鍵字的實(shí)現(xiàn)原理才能掌握他們的正確使用方法,請參考apple?
object c文檔中舉的例子來了解為什么非常容易出錯(cuò)。
上面我們提到了method在被調(diào)用的時(shí)候,會(huì)被傳入隱含參數(shù),第一個(gè)隱含參數(shù)就是object的地址,self實(shí)際上在編譯期間被替換成了
ojbect的地址,所以堆self發(fā)送的消息都是根標(biāo)準(zhǔn)流程一樣通過isa鏈找到method來執(zhí)行。
super就不一樣,super關(guān)鍵字被編譯器替換成了
id objc_msgSendSuper(struct objc_super *super, SEL op,??...)
其中objc_super的結(jié)構(gòu)是
struct objc_super
{
id receiver;
Class class;
};
注意到
objc_msgSendSuper
和
id objc_msgSend(id theReceiver, SEL theSelector, ...)的區(qū)別,多了一個(gè)Class class;
class實(shí)際上就指向了找到當(dāng)前method的class 對象的實(shí)例。
所以在objc_msgSendSuper中查找方法是從參數(shù)class指向的class 實(shí)例對象的isa開始查找的,而不是從theReceiver也就是myobj
這個(gè)對象的isa開始查找的
總結(jié)
以上是生活随笔為你收集整理的object c中的多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 商城系统订单超时自动取消解决方案
- 下一篇: word多级标题下一级和上一级没有关联上