Dynamicaly Typed(動態定型), Objective-C Runtime Programming

  Objective-C跟C最大的差異,應該是動態定型(dynamicaly typed),支持在運行時動態類型決議(dynamic typing),動態綁定(dynamic binding)以及動態裝載(dynamic loading)。Objective-C 在運行時能夠容許根據字符串名字來訪問方法和類,還能夠動態鏈接和添加類,而C語言編譯時靜態綁定,甚至不少時候你沒定義的方法直接就編譯不過。編程

Message編程語言

  Messaging是Object-C動態定型的實現方法。當調用一個類方法時,系統就給這個對象發消息:ide

  objc_msgSend(receiver, selector, arg1, arg2, ...)
id target = getTheReceiver(); SEL method = getTheMethod(); if ( target == self || method == _cmd )[target performSelector:method];

 

 receiver指定哪一個對象接收消息,selector是調用方法,arg1..後面是參數。函數

 因此每一個類有兩個必須的基本元素:ui

 1.A pointer to the superclass.(指向superclass的指針)spa

   2.A class dispatch table. (一張本身所支持方法的分發表)代理

  當它收到一個消息時message,它取出selector,而後遍歷本身的dispatch table,若是在dispatch table,就去執行,不然把message傳遞給super。指針

Message Forwardingcode

既然Object-C是動態綁定,當它運行時,收到一個不支持的消息,那一定會出現異常,不特殊處理這個異常的話,程序就崩潰了。不過幸運的是,系統能夠在error出現以前,經過判斷對象是否是能調用這個方法:(negotiate表明你須要執行的函數)orm

- negotiate { if ( [someOtherObject respondsTo:@selector(negotiate)] ) return [someOtherObject negotiate]; }

不過這種方法就很笨重了,每個方法就寫一個函數,甚至不少時候你都不知道你須要支持什麼函數,因此應該用以下方法來處理未支持的消息:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { if ([self respondsToSelector:aSelector]) { return [super methodSignatureForSelector:aSelector]; } else {   //不支持的方法隨便返回一個NSMethodSignature,固然不能返回nil,不然仍是會崩潰
        return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } } -(void)forwardInvocation:(NSInvocation *)anInvocation { if ([self respondsToSelector: [anInvocation selector]]) [anInvocation invokeWithTarget:self]; else{ //什麼作,就不崩潰了
 } }

 

這兩個方法能夠從NSobject繼承重寫,從anInvocation取出selector,若是是支持的就激活invoke,不然就無論了。經過重寫這兩個函數,即便這個類調用了不支持的方法,也不會致使程序崩潰了。

既然這個方法能夠防止系統崩潰,爲何系統不直接實現呢?估計仍是效率問題,若是接收每一個message都去判斷是否是支持,那一定會耗費時間。

 

Surrogate Objects 

這裏就簡單說說surrogate。代理,顧名思義,也就是能夠把對象接受到的消息轉給一個代理object處理。也是經過重寫上面說的兩個函數:

//surrogateObject1和surrogateObject2就是self的兩個對象,用來做爲self的代理,把self收到的消息轉給surrogateObject1或2處理

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { //對不一樣的aSelector,是返回self,仍是返回surrogateObject1或surrogateObject2的NSMethodSignature就可
} - (void)forwardInvocation:(NSInvocation *)invocation { //同理,對不一樣的selector,激活self或者是surrogateObject1或surrogateObject2
}  

通常沒怎麼用。你們能夠本身看看。

 

通常來講,瞭解編程語言的特徵,對編寫程序仍是頗有必要的。僅供參考。

參考資料:ObjCRuntimeGuide.pdf(iOS官方文檔)

相關文章
相關標籤/搜索