Objective-C函數消息機制的理解

  C語言中,函數調用過程:C語言中,編譯完成後,函數名就是指向函數入口的地址,調用函數就是直接執行這個地址的代碼。

  而Objectiv-C是間接的方式,函數調用是向類或者對象發送消息,比如:[MyClass new],向MyClass發送消息new,查找MyClass的消息列表,如果找到new函數執行,MyClass裏沒找到就去父類中繼續找,找不到就出錯。

  通過這種消息機制,Objective-C也能實現多態。

SEL類型

讓我們接着看“DoProxy.h”文件的下列代碼:

1     id cattle[3];
2     SEL say;
3     SEL skin;

其中id cattle[3]定義了一個數組用於存儲Cattle或者Bull對象。這一行代碼估計大家都很熟悉,筆者就不贅述了。像這樣的傳統的數組並不能完全滿足我們的需求,當我們需要做諸如追加,刪除等操作的時候,會很不方便。在隨後的章節裏面筆者將要向大家介紹傳統數組的替代解決方案NSArray。

 

上一段代碼的第二行和第三行是本節所關注的,就是SEL類型。Objective-C在編譯的時候,會根據方法的名字(包括參數序列),生成一個用 來區分這個方法的唯一的一個ID,這個ID就是SEL類型的。我們需要注意的是,只要方法的名字(包括參數序列)相同,那麼它們的ID都是相同的。就是 說,不管是超類還是子類,不管是有沒有超類和子類的關係,只要名字相同那麼ID就是一樣的。除了函數名字和ID,編譯器當然還要把方法編譯成爲機器可以執 行的代碼,這樣,在一個編譯好的類裏面,就產生了如下圖所示方法的表格示意圖(本構造屬於筆者推測,沒有得到官方證實,所以圖5-2爲示意圖僅供參考,我們可以暫時認爲是這樣的)。

 

圖5-2,方法的表格示意圖 

請注意setSkinColor後面有一個冒號,因爲它是帶參數的。由於存在這樣的一個表格,所以在程序執行的時候,我們可以方便的通過方法的名字,獲取到方法的ID也就是我們所說的SEL,反之亦然。具體的使用方法如下:

1     SEL 變量名 = @selector(方法名字);
2     SEL 變量名 = NSSelectorFromString(方法名字的字符串);
3     NSString *變量名 = NSStringFromSelector(SEL參數);

其中第1行是直接在程序裏面寫上方法的名字,第2行是寫上方法名字的字符串,第3行是通過SEL變量獲得方法的名字。我們得到了SEL變量之後,可以通過下面的調用來給一個對象發送消息:

[對象 performSelector:SEL變量 withObject:參數1 withObject:參數2];

這樣的機制大大的增加了我們的程序的靈活性,我們可以通過給一個方法傳遞SEL參數,讓這個方法動態的執行某一個方法;我們也可以通過配置文件指定需要執行的方法,程序讀取配置文件之後把方法的字符串翻譯成爲SEL變量然後給相應的對象發送這個消息。

從效率的角度上來說,執行的時候不是通過方法名字而是方法ID也就是一個整數來查找方法,由於整數的查找和匹配比字符串要快得多,所以這樣可以在某種程度上提高執行的效率。 


發佈了55 篇原創文章 · 獲贊 4 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章