主要是學習Objective-C的“多繼承”——消息轉發(fā)博客怖喻。
具體的代碼是 : OC2Nature項目中 SendMSG 目錄如孝, 歡迎下載查看,謝謝颜凯!
Objective-C 不支持多繼承谋币,但是也能做到多繼承的效果,具體方式有:消息轉發(fā)症概、delegate與protocol蕾额、類別。
Objective-C 與 消息轉發(fā) 是什么關系呢彼城?還有一個專業(yè)名詞叫消息機制诅蝶。 在 Objective-C 中的 消息機制 發(fā)生在運行時,與編譯時沒有任何關系募壕。
Objective-C是一門動態(tài)語言调炬,一個函數(shù)是由一個selector(SEL),和一個implement(IML)組成的舱馅。Selector相當于門牌號缰泡,而Implement才是真正的住戶(函數(shù)實現(xiàn))。和現(xiàn)實生活一樣代嗤,門牌可以隨便發(fā)(@selector(XXX))棘钞,但是不一定都找得到住戶,如果找不到系統(tǒng)會給程序幾次機會來程序正常運行干毅,實在沒出路了才會拋出異常宜猜。
引用中提到的門牌可以隨便發(fā),是這個意思:
[receiver performSelector:@selector(message)];
在上面的message在代碼中可以順便寫,在編譯階段不會報錯硝逢,只會有警告而已姨拥,所以才說門牌可以隨便發(fā)。其中 performSelector: 是系統(tǒng)發(fā)送消息的方法, message 就是所謂的門牌號渠鸽。上面的語句可以理解成 拿著 message 這個門牌號到receiver對象中去尋找implement(IML)(具體實現(xiàn))叫乌,如果找到了就執(zhí)行,如果沒有找到就奔潰徽缚。
還有一種說法:每發(fā)送一個消息(message)综芥,知道程序運行的時候才會去尋找具體的實現(xiàn)(IML),在Objective-C中國年發(fā)送一條消息的經(jīng)典表達式如下:
[receiver message];
最終在運行時轉成了這樣的格式:
objc_msgSend(receiver, @selector(message))
其中 objc_msgSend 可以有參數(shù),如:
objc_msgSend(receiver, @selector(message), arg1,arg2)
是怎么通過門牌號去尋找具體的IML的呢猎拨?Objective-C的“多繼承”——消息轉發(fā)是使用下圖解釋的:
動態(tài)消息解析
快速消息轉發(fā)
主要是重寫如下系統(tǒng)方法:
- (id)forwardingTargetForSelector:(SEL)aSelector
按照我的理解應該是這樣的:當前對象收到一個aSelector的時候膀藐, 先檢查一下自己能否執(zhí)行, 若是不能執(zhí)行的話红省,就在這里交給別人執(zhí)行吧额各。這個方法執(zhí)行是有條件的,在動態(tài)方法沒有找到的情況下才會被執(zhí)行吧恃。
// Teacher 類需要實現(xiàn)將消息轉發(fā)給 Doctor
- (id)forwardingTargetForSelector:(SEL)aSelector {
// 醫(yī)生
Doctor *doctor = [[Doctor alloc]init];
if ([doctor respondsToSelector:aSelector]) {
return doctor;
}
// 返回 nil 說明快速消息轉發(fā)失敗
return nil;
}
標準消息轉發(fā)
當快速消息轉發(fā)返回 nil 的時候虾啦,會到標準消息轉發(fā)。主要是重寫以下兩個系統(tǒng)方法:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
以下是參考截圖
一個小 Demo
以上均是參考各位大神的博客的抄襲總結痕寓,由于這些方法通常也用不到傲醉,過一段時間來看的話感覺又模糊了,故特弄了一個 Demo呻率,以便后期方便查看硬毕。具體的代碼是 : OC2Nature項目中 SendMSG 目錄, 歡迎下載查看礼仗,謝謝吐咳!
參考
0、Objective-C的“多繼承”——消息轉發(fā)
1元践、蘋果
2韭脊、繼承自NSObject的不常用又很有用的函數(shù)(2)
3、消息機制