作者:菩提树下的杨过
出处:http://www.cnblogs.com/yjmyzz/archive/2011/02/28/1967451.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
ObjC(Objective-C)中的Class(类类型),Selector(选择器SEL),函数指针(IMP)
个人体会:obj-C中的“Class类型变量”比c#中的Object基类还要灵活,可以用它生成任何类型的实例(但是它又不是 NSObject)。而选择器SEL与函数指针IMP,如果非要跟c#扯上关系的话,这二个结合起来,就点类似c#中的反射+委托,可以根据一个方法名称 字符串,直接调用方法。
"牛"的基类 Cattle.h
1 |
#import <Foundation/Foundation.h> |
3 |
@interface Cattle : NSObject { |
7 |
- (void)setLegsCount:(int) count; |
Cattle.m
03 |
@implementation Cattle |
07 |
NSLog(@"Hello, I am a cattle, I have %d legs.", legsCount); |
10 |
-(void) setLegsCount:(int) count |
子类“公牛" Bull.h
01 |
#import <Foundation/Foundation.h> |
04 |
@interface Bull : Cattle { |
08 |
- (NSString*) getSkinColor; |
09 |
- (void) setSkinColor:(NSString *) color; |
Bull.m
08 |
NSLog(@"Hello, I am a %@ bull, I have %d legs.", [self getSkinColor],legsCount); |
11 |
-(NSString*) getSkinColor |
16 |
- (void) setSkinColor:(NSString *) color |
代理类DoProxy.h (关键的代码都在这里)
01 |
#import <Foundation/Foundation.h> |
04 |
#define SET_SKIN_COLOR @"setSkinColor:" |
05 |
#define BULL_CLASS @"Bull" |
06 |
#define CATTLE_CLASS @"Cattle" |
09 |
@interface DoProxy : NSObject { |
18 |
void(*setSkinColor_Func)(id,SEL,NSString*); |
27 |
-(void) doWithCattleId:(id) aCattle colorParam:(NSString*) color; |
30 |
-(void) functionPointers; |
DoProxy.m
05 |
@implementation DoProxy |
11 |
cattle[0] = [Cattle new]; |
13 |
bullClass = NSClassFromString(BULL_CLASS); |
15 |
cattle[1] = [bullClass new]; |
16 |
cattle[2] = [bullClass new]; |
18 |
say = @selector(saySomething); |
19 |
skin = NSSelectorFromString(SET_SKIN_COLOR); |
24 |
- (void) doWithCattleId:(id) aCattle colorParam:(NSString*) color |
29 |
NSString *myName = NSStringFromSelector(_cmd); |
30 |
NSLog(@"Running in the method of %@", myName); |
34 |
NSString *cattleParamClassName = [aCattle className]; |
37 |
if([cattleParamClassName isEqualToString:BULL_CLASS] || [cattleParamClassName isEqualToString:CATTLE_CLASS]) |
39 |
[aCattle setLegsCount:4]; |
40 |
if([aCattle respondsToSelector:skin]) |
42 |
[aCattle performSelector:skin withObject:color]; |
46 |
NSLog(@"Hi, I am a %@, have not setSkinColor!", cattleParamClassName); |
48 |
[aCattle performSelector:say]; |
52 |
NSString *yourClassName = [aCattle className]; |
53 |
NSLog(@"Hi, you are a %@, but I like cattle or bull!", yourClassName); |
60 |
[self doWithCattleId:cattle[0] colorParam:@"brown"]; |
61 |
[self doWithCattleId:cattle[1] colorParam:@"red"]; |
62 |
[self doWithCattleId:cattle[2] colorParam:@"black"]; |
63 |
[self doWithCattleId:self colorParam:@"haha"]; |
67 |
- (void) functionPointers |
70 |
setSkinColor_Func=(void (*)(id, SEL, NSString*)) [cattle[1] methodForSelector:skin]; |
75 |
say_Func = [cattle[1] methodForSelector:say]; |
78 |
setSkinColor_Func(cattle[1],skin,@"verbose"); |
80 |
NSLog(@"Running as a function pointer will be more efficiency!"); |
83 |
say_Func(cattle[1],say); |
测试主函数main()
01 |
#import <Foundation/Foundation.h> |
04 |
int main (int argc, const char * argv[]) { |
05 |
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; |
06 |
DoProxy *doProxy = [DoProxy new]; |
08 |
[doProxy setAllIVars]; |
10 |
[doProxy functionPointers]; |
运行结果:
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.