作者:菩提树下的杨过
出处: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.