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