事實上,在訊息傳遞的過程,當 someObject 這傢伙收到訊息之後,會順著這個物件的 isa 指針找到自己的類別,然後再依照收到的「訊息」去類別的 method list 找出對應的方法。如果在這個類別裡面找到了,就會直接執行它,如果找不到,會再往上一層父類別(super class)找。以上這個流程都是在程式執行過程中(Rumtime)才動態決定的,而不是在編譯(Compile)時期就決定好的。
// Animal Class@interfaceAnimal : NSObject@end@implementationAnimal@end// Fox Class@interfaceFox : Animal-(void)say;@end@implementationFox-(void)say{NSLog(@"What does the fox say!?");}@end
上面這段程式碼建立了兩個類別,分別是 Animal 及 Fox ,而且 Fox 繼承自 Animal,而 Animal 類別則是繼承自 NSObject 類別。
不管是「物件」或是「類別」,因為一樣都是物件,所以他們在收到訊息時的反應流程也是一樣的:
當對「物件」發送訊息的時候,它會順著這個物件的 isa 指針找到它的所屬類別,然後翻看看這個類別的 method list 有沒有符合的方法可以執行;
當對「類別」發送訊息的時候,它會順著這個類別的 isa 指針找到它的所屬類別(也就是我們待會要說明的 Meta Class),然後翻看看這個類別的 method list 有沒有符合的方法可以執行。
什麼是 Meta Class?
Meta 這個字我不太懂中文該怎麼翻譯比較好,有人翻譯成「元」,有人翻譯成「後設」,但我個人還是喜歡直接使用 Meta 這個詞就好。
剛剛在看類別的 objc_class 的定義的時候有提到類別的 Struct 裡也有一個 isa 指針,指向它所屬的類別,你可以想像成是它是「類別的類別」,也就是所謂的 Meta Class。
而 Meta Class 其實也是一種類別,所以也跟一般的類別一樣有 isa 跟 super_class 指針… 所以就可以把這整個的關係用一張圖表來解釋:
看圖說故事:
每個 Class (Fox, Animal, NSObject) 的 isa 指針都指向一個唯一的 Class,這個 Class 稱之為 Meta Class。
每個 Meta Class 的 isa 指針都是指向最上層的 Meta Class (在我們上面那段範例裡,就是 NSObject 的 Meta Class),而最上層的 Meta Class 的 isa 則是指向自己,形成一個迴路。
每個 Meta Class 的 super_class 指針都是指向它原本類別的 Super Class 的 Meta Class,但最上層的 Meta Class 的 super_class 則是指向 NSObject 類別本身。
Fox*lucky=[[Foxalloc]init];[luckysay];// about fox instanceNSLog(@"the class of lucky is %@, address = %p",[luckyclass],[luckyclass]);// about Fox classNSLog(@"Fox = %@, address = %p",[Foxclass],[Foxclass]);NSLog(@"Fox's Super Class = %@, address = %p",[Foxsuperclass],[Foxsuperclass]);ClassmetaClassOfFox=object_getClass([Foxclass]);NSLog(@"Fox's Meta Class = %p",metaClassOfFox);NSLog(@"Fox's Meta Class's Super Class = %p",[metaClassOfFoxsuperclass]);ClassmetaMetaClassOfFox=object_getClass(metaClassOfFox);NSLog(@"Fox's Meta Class's Meta Class = %p",metaMetaClassOfFox);// about Animal classNSLog(@"Animal = %@, address = %p",[Animalclass],[Animalclass]);NSLog(@"Animal's Super Class = %@, address = %p",[Animalsuperclass],[Animalsuperclass]);ClassmetaClassOfAnimal=object_getClass([Animalclass]);NSLog(@"Animal's Meta Class = %p",metaClassOfAnimal);NSLog(@"Animal's Meta Class's Super Class = %p",[metaClassOfAnimalsuperclass]);ClassmetaMetaClassOfAnimal=object_getClass(metaClassOfAnimal);NSLog(@"Animal's Meta Class's Meta Class = %p",metaMetaClassOfAnimal);// about NSObject classNSLog(@"NSObject = %@, address = %p",[NSObjectclass],[NSObjectclass]);NSLog(@"NSObject's Super Class = %@, address = %p",[NSObjectsuperclass],[NSObjectsuperclass]);ClassmetaClassOfNSObject=object_getClass([NSObjectclass]);NSLog(@"NSObject's Meta Class = %p",metaClassOfNSObject);NSLog(@"NSObject's Meta Class's Super Class = %p",[metaClassOfNSObjectsuperclass]);ClassmetaMetaClassOfNSObject=object_getClass(metaClassOfNSObject);NSLog(@"NSObject's Meta Class's Meta Class = %p",metaMetaClassOfNSObject);
輸出結果如下:
What does the fox say!?
the class of lucky is Fox, address = 0x100002260
Fox = Fox, address = 0x100002260
Fox's Super Class = Animal, address = 0x100002210
Fox's Meta Class = 0x100002238
Fox's Meta Class's Super Class = 0x1000021e8
Fox's Meta Class's Meta Class = 0x7fff77cce838
Animal = Animal, address = 0x100002210
Animal's Super Class = NSObject, address = 0x7fff77cce810
Animal's Meta Class = 0x1000021e8
Animal's Meta Class's Super Class = 0x7fff77cce838
Animal's Meta Class's Meta Class = 0x7fff77cce838
NSObject = NSObject, address = 0x7fff77cce810
NSObject's Super Class = (null), address = 0x0
NSObject's Meta Class = 0x7fff77cce838
NSObject's Meta Class's Super Class = 0x7fff77cce810
NSObject's Meta Class's Meta Class = 0x7fff77cce838
輸出結果可能在每個人的電腦上都不一樣,但從輸出的結果就能證明上面那張圖片的每個類別之間的關係。
要特別注意的是,你可能會覺得直接對類別發送 class 訊息就可以得到該類別的 Meta Class,事實上直接對類別發送 class 訊息只會得到該類別自己。要取得類別的 Meta Class,可以透過 object_getClass 來取得。
分心團隊雖然是個新創團隊,但裡面的成員都不會太新手,有眼光犀利的UI、UX designer 讓整個 app 看起來很精緻,使用起來也更直覺;有優秀的工程師負責處理 API,也有專門負責行銷及想點子的同事,讓開發人員可以 專心的開發 app;除此之外,還有 Web 平台的開發人員,讓 Web 跟 Mobile 都有一樣的功能。在這短短的八個多月的時間跟大家學到不少。