ObjC(Objective-C)中的Class(類類型),Selector(選取器SEL),函數指標(IMP)

來源:互聯網
上載者:User
今天在園子裡看到了一篇牛文“Objective-C 2.0 with Cocoa Foundation--- 5,Class類型,選取器Selector以及函數指標 ”,講得十分精彩,忍不住把它的代碼加上注釋整理於此,以便日後查看。個人體會:obj-C中的“Class類型變數”比c#中的Object基類還要靈活,可以用它產生任何類型的執行個體(但是它又不是
NSObject)。而選取器SEL與函數指標IMP,如果非要跟c#扯上關係的話,這二個結合起來,就點類似c#中的反射+委託,可以根據一個方法名稱
字串,直接調用方法。"牛"的基類 Cattle.h
#import <Foundation/Foundation.h>@interface Cattle : NSObject {int legsCount;}- (void)saySomething;- (void)setLegsCount:(int) count;@end
Cattle.m
#import "Cattle.h"@implementation Cattle-(void) saySomething{NSLog(@"Hello, I am a cattle, I have %d legs.", legsCount);}-(void) setLegsCount:(int) count{legsCount = count;}@end
子類“公牛" Bull.h
#import <Foundation/Foundation.h>#import "Cattle.h"@interface Bull : Cattle {NSString *skinColor;}- (void)saySomething;- (NSString*) getSkinColor;- (void) setSkinColor:(NSString *) color;@end
Bull.m
#import "Bull.h"@implementation Bull-(void) saySomething{NSLog(@"Hello, I am a %@ bull, I have %d legs.", [self getSkinColor],legsCount);}-(NSString*) getSkinColor{return skinColor;}- (void) setSkinColor:(NSString *) color{skinColor = color;}@end
代理類DoProxy.h (關鍵的代碼都在這裡)
#import <Foundation/Foundation.h>//定義幾個字串常量#defineSET_SKIN_COLOR @"setSkinColor:"#defineBULL_CLASS @"Bull"#defineCATTLE_CLASS @"Cattle"@interface DoProxy : NSObject {BOOL notFirstRun;id cattle[3];//定義二個選取器SEL say;SEL skin;//定義一個函數指標(傳統C語言的處理方式)void(*setSkinColor_Func)(id,SEL,NSString*);//定義一個IMP方式的函數指標(obj-C中推薦的方式)IMP say_Func;//定義一個類Class bullClass;}-(void) doWithCattleId:(id) aCattle colorParam:(NSString*) color;-(void) setAllIVars;-(void) SELFuncs;-(void) functionPointers;@end
DoProxy.m
#import "DoProxy.h"#import "Cattle.h"#import "Bull.h"@implementation DoProxy//初始化所有變數- (void) setAllIVars{cattle[0] = [Cattle new];bullClass = NSClassFromString(BULL_CLASS);//即cattle[1],cattle[2]都是Bull類的執行個體cattle[1] = [bullClass new];cattle[2] = [bullClass new];say = @selector(saySomething);skin = NSSelectorFromString(SET_SKIN_COLOR);}//初始化id- (void) doWithCattleId:(id) aCattle colorParam:(NSString*) color{//第一次啟動並執行時候if(notFirstRun == NO){NSString *myName = NSStringFromSelector(_cmd);//取得當前正在執行的方法的名字NSLog(@"Running in the method of %@", myName);notFirstRun = YES;//修改初次運行標誌位}NSString *cattleParamClassName = [aCattle className];//取得aCattle的"類名稱"//如果aCattle是Bull或Cattle類的執行個體if([cattleParamClassName isEqualToString:BULL_CLASS] || [cattleParamClassName isEqualToString:CATTLE_CLASS]){[aCattle setLegsCount:4];//設定牛的4條腿if([aCattle respondsToSelector:skin])//如果aCattle對應的是類中,有定義方法"setSkinColor"{[aCattle performSelector:skin withObject:color];//則調用setSkinColor方法}else{NSLog(@"Hi, I am a %@, have not setSkinColor!", cattleParamClassName);//否則輸出相應的提示資訊}[aCattle performSelector:say];//最後執行saySomething方法(這二個方法在Bull與Cattle類中都有,所以肯定能運行)}else //如果aCattle即不是Bull類也不是Cattle類的執行個體{NSString *yourClassName = [aCattle className];NSLog(@"Hi, you are a %@, but I like cattle or bull!", yourClassName);//顯示這個"異類"的相關資訊}}//初始化選取器以及相應函數- (void) SELFuncs{[self doWithCattleId:cattle[0] colorParam:@"brown"];[self doWithCattleId:cattle[1] colorParam:@"red"];[self doWithCattleId:cattle[2] colorParam:@"black"];[self doWithCattleId:self colorParam:@"haha"];//這裡故意傳入一個異類self(即DoProxy本身),DoProxy當然不是Bull或Cattle}//函數指標測試- (void) functionPointers{//取得函數指標的第一種方式setSkinColor_Func=(void (*)(id, SEL, NSString*)) [cattle[1] methodForSelector:skin];//上面的語句其實等效於下面這種方法//IMP setSkinColor_Func = [cattle[1] methodForSelector:skin];//用第二種方法取得saySomething的函數指標say_Func = [cattle[1] methodForSelector:say];//用函數指標的形式調用setSkinColorsetSkinColor_Func(cattle[1],skin,@"verbose");NSLog(@"Running as a function pointer will be more efficiency!");//調用saySomething方法say_Func(cattle[1],say); }@end
測試主函數main()
#import <Foundation/Foundation.h>#import "DoProxy.h"int main (int argc, const char * argv[]) {NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];DoProxy *doProxy = [DoProxy new];[doProxy setAllIVars];[doProxy SELFuncs];[doProxy functionPointers];[doProxy release];[pool drain];return 0;}

運行結果:

2011-02-28 21:40:33.240 HelloSelector[630:a0f] Running in the method of doWithCattleId:colorParam:
2011-02-28 21:40:33.245 HelloSelector[630:a0f] Hi, I am a Cattle, have not setSkinColor!
2011-02-28 21:40:33.247 HelloSelector[630:a0f] Hello, I am a cattle, I have 4 legs.
2011-02-28 21:40:33.248 HelloSelector[630:a0f] Hello, I am a red bull, I have 4 legs.
2011-02-28 21:40:33.250 HelloSelector[630:a0f] Hello, I am a black bull, I have 4 legs.
2011-02-28 21:40:33.251 HelloSelector[630:a0f] Hi, you are a DoProxy, but I like cattle or bull!
2011-02-28 21:40:33.252 HelloSelector[630:a0f] Running as a function pointer will be more efficiency!
2011-02-28 21:40:33.254 HelloSelector[630:a0f] Hello, I am a verbose bull, I have 4 legs.

作者:菩提樹下的楊過
出處:http://www.cnblogs.com/yjmyzz/archive/2011/02/28/1967451.html
本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.