標籤:
寫完標題,我也撲通一笑.就先來對標題透一下劇吧.
"誰說我不能執行你":應該把"我"與"你"理解成OC語言中不同類的執行個體對象.<IT男永遠不孤單,因為IT男搞的就是面向對象的編程>
是的,在今天之前,我是不相信:我能執行你.但是,現在我相信了,沒想到我是如此的強大,只是我沒有發現而已!
之前,我一直是這樣認為的:在iOS開發中,A類的對象a,是不能去執行B類中的執行個體方法的.其實不是這樣的.
的確,在iOS中,是沒有多繼承的,只有單繼承.在其它語言中,很容易實現兩個不同類的對象去擁有同一個方法,因為他們是多繼承的,他們就好比兩個男生能擁有同一個妹子一樣.iOS就沒那麼泛濫,是很單純的,因為只有單繼承.
現實中,需求是千奇百怪的.特殊情況,需要特殊處理.有時候在iOS開發中,也需要A類的對象a去執行B類中的執行個體方法.為了達到這一點,先來介紹一下訊息轉寄機制.
訊息轉寄
其實,當向某個對象發送某個訊息時,runtime system在當前和父類中都找不到對應的實現方法是,runtime system並不會立即報錯誤使程式崩潰,而是依次執行下列步驟:
1,動態方法
像當前類發送+ (BOOL)resolveInstanceMethod:(SEL)sel訊號,檢查是否動態向該類添加了方法.可進入這個部落格查看:http://blog.csdn.net/haishu_zheng/article/details/12873151
2,快速訊息轉寄
檢查該類是否實現了- (id)forwardingTargetForSelector:(SEL)aSelector方法,若實現了則調用這個方法.若該方法傳回值對象非nil或者分self,則向該返回對象從新發送訊息.
3,標準訊息轉寄
runtime發送- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector訊息擷取selector對應方法簽名.傳回值非空則通過- (void)forwardInvocation:(NSInvocation *)anInvocation轉寄訊息,傳回值為空白則像當前對象發送doesNotRecognizeSelector:訊息,程式崩潰退出.
總結:能用以上2,3方式實現訊息的轉寄.
快速訊息轉寄
快速訊息轉寄的實現方法很簡單,只需要重寫 - (id)forwardingTargetForSelector:(SEL)aSelector 方法即可。
我來舉個簡單的例子,比如現有2個類:Teacher 和 Doctor,Doctor可以做手術(operate方法)。
Teacher.h
#import <Foundation/Foundation.h>
@interface Teacher : NSObject
@end
Teacher.m
#import "Teacher.h"
#import "Doctor.h"
@implementation Teacher
- (id)forwardingTargetForSelector:(SEL)aSelector {
Doctor* doctor = [[Doctor alloc] init];
if ([doctor respondsToSelector:aSelector]) {
return doctor;
}
return nil;
}
@end
Doctor.h
#import <Foundation/Foundation.h>
@interface Doctor : NSObject
- (void)operate;
@end
Doctor.m
#import "Doctor.h"
@implementation Doctor
- (void)operate; {
NSLog(@"operate");
}
@end
到這裡還差一步,再弄一個分類.具體是為什麼,自己想.
Teacher+DoctorMethod.h
#import "Teacher.h"
@interface Teacher (DoctorMethod)
- (void)operate;
@end
Teacher+DoctorMethod.m
#import "Teacher+DoctorMethod.h"
@implementation Teacher (DoctorMethod)
@end
ok,現在可以到main.m中了
#import <Foundation/Foundation.h>
#import "Teacher.h"
#import "Teacher+DoctorMethod.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Teacher* teacher = [[Teacher alloc] init];
[teacher operate];
}
return 0;
}
log:2015-04-26 17:45:45.134 Quichly[3304:381361] operate
成功了!
標準訊息轉寄 <待續...>
iOS&誰說我不能執行你