作者:菩提树下的杨过
出处:http://www.cnblogs.com/yjmyzz/archive/2011/02/28/1967451.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
ObjC(Objective-C)中的Class(类类型),Selector(选择器SEL),函数指针(IMP)
1 |
#import <Foundation/Foundation.h> |
2 |
3 |
@interface Cattle : NSObject {
|
4 |
int legsCount;
|
5 |
} |
6 |
- ( void )saySomething;
|
7 |
- ( void )setLegsCount:( int ) count;
|
8 |
@end |
01 |
#import "Cattle.h" |
02 |
03 |
@implementation Cattle
|
04 |
05 |
-( void ) saySomething
|
06 |
{ |
07 |
NSLog (@ "Hello, I am a cattle, I have %d legs." , legsCount);
|
08 |
} |
09 |
10 |
-( void ) setLegsCount:( int ) count
|
11 |
{ |
12 |
legsCount = count;
|
13 |
} |
14 |
@end |
01 |
#import <Foundation/Foundation.h> |
02 |
#import "Cattle.h" |
03 |
04 |
@interface Bull : Cattle {
|
05 |
NSString *skinColor;
|
06 |
} |
07 |
- ( void )saySomething;
|
08 |
- ( NSString *) getSkinColor;
|
09 |
- ( void ) setSkinColor:( NSString *) color;
|
10 |
@end |
01 |
#import "Bull.h" |
02 |
03 |
04 |
@implementation Bull
|
05 |
06 |
-( void ) saySomething
|
07 |
{ |
08 |
NSLog (@ "Hello, I am a %@ bull, I have %d legs." , [ self getSkinColor],legsCount);
|
09 |
} |
10 |
11 |
-( NSString *) getSkinColor
|
12 |
{ |
13 |
return skinColor;
|
14 |
} |
15 |
16 |
- ( void ) setSkinColor:( NSString *) color
|
17 |
{ |
18 |
skinColor = color;
|
19 |
} |
20 |
@end |
01 |
#import <Foundation/Foundation.h> |
02 |
03 |
//定义几个字符串常量 |
04 |
#define SET_SKIN_COLOR @"setSkinColor:" |
05 |
#define BULL_CLASS @"Bull" |
06 |
#define CATTLE_CLASS @"Cattle" |
07 |
08 |
09 |
@interface DoProxy : NSObject {
|
10 |
BOOL notFirstRun;
|
11 |
|
12 |
id cattle[3];
|
13 |
//定义二个选择器
|
14 |
SEL say;
|
15 |
SEL skin;
|
16 |
|
17 |
//定义一个函数指针(传统C语言的处理方式)
|
18 |
void (*setSkinColor_Func)( id , SEL , NSString *);
|
19 |
|
20 |
//定义一个IMP方式的函数指针(obj-C中推荐的方式)
|
21 |
IMP say_Func;
|
22 |
|
23 |
//定义一个类
|
24 |
Class bullClass;
|
25 |
} |
26 |
27 |
-( void ) doWithCattleId:( id ) aCattle colorParam:( NSString *) color;
|
28 |
-( void ) setAllIVars;
|
29 |
-( void ) SELFuncs;
|
30 |
-( void ) functionPointers;
|
31 |
32 |
@end |
01 |
#import "DoProxy.h" |
02 |
#import "Cattle.h" |
03 |
#import "Bull.h" |
04 |
05 |
@implementation DoProxy
|
06 |
07 |
08 |
//初始化所有变量 |
09 |
- ( void ) setAllIVars
|
10 |
{ |
11 |
cattle[0] = [Cattle new ];
|
12 |
|
13 |
bullClass = NSClassFromString (BULL_CLASS);
|
14 |
//即cattle[1],cattle[2]都是Bull类的实例
|
15 |
cattle[1] = [bullClass new ];
|
16 |
cattle[2] = [bullClass new ];
|
17 |
|
18 |
say = @selector (saySomething);
|
19 |
skin = NSSelectorFromString (SET_SKIN_COLOR);
|
20 |
} |
21 |
22 |
23 |
//初始化id |
24 |
- ( void ) doWithCattleId:( id ) aCattle colorParam:( NSString *) color
|
25 |
{ |
26 |
//第一次运行的时候
|
27 |
if (notFirstRun == NO )
|
28 |
{
|
29 |
NSString *myName = NSStringFromSelector (_cmd); //取得当前正在执行的方法的名字
|
30 |
NSLog (@ "Running in the method of %@" , myName);
|
31 |
notFirstRun = YES ; //修改初次运行标志位
|
32 |
}
|
33 |
|
34 |
NSString *cattleParamClassName = [aCattle className]; //取得aCattle的"类名称"
|
35 |
|
36 |
//如果aCattle是Bull或Cattle类的实例
|
37 |
if ([cattleParamClassName isEqualToString:BULL_CLASS] || [cattleParamClassName isEqualToString:CATTLE_CLASS])
|
38 |
{
|
39 |
[aCattle setLegsCount:4]; //设置牛的4条腿
|
40 |
if ([aCattle respondsToSelector:skin]) //如果aCattle对应的是类中,有定义方法"setSkinColor"
|
41 |
{
|
42 |
[aCattle performSelector:skin withObject:color]; //则调用setSkinColor方法
|
43 |
}
|
44 |
else
|
45 |
{
|
46 |
NSLog (@ "Hi, I am a %@, have not setSkinColor!" , cattleParamClassName); //否则输出相应的提示信息
|
47 |
}
|
48 |
[aCattle performSelector:say]; //最后执行saySomething方法(这二个方法在Bull与Cattle类中都有,所以肯定能运行)
|
49 |
}
|
50 |
else //如果aCattle即不是Bull类也不是Cattle类的实例
|
51 |
{
|
52 |
NSString *yourClassName = [aCattle className];
|
53 |
NSLog (@ "Hi, you are a %@, but I like cattle or bull!" , yourClassName); //显示这个"异类"的相关信息
|
54 |
}
|
55 |
} |
56 |
57 |
//初始化选择器以及相应函数 |
58 |
- ( void ) SELFuncs
|
59 |
{ |
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" ]; //这里故意传入一个异类self(即DoProxy本身),DoProxy当然不是Bull或Cattle
|
64 |
} |
65 |
66 |
//函数指针测试 |
67 |
- ( void ) functionPointers
|
68 |
{ |
69 |
//取得函数指针的第一种方式
|
70 |
setSkinColor_Func=( void (*)( id , SEL , NSString *)) [cattle[1] methodForSelector:skin];
|
71 |
//上面的语句其实等效于下面这种方法
|
72 |
//IMP setSkinColor_Func = [cattle[1] methodForSelector:skin];
|
73 |
|
74 |
//用第二种方法取得saySomething的函数指针
|
75 |
say_Func = [cattle[1] methodForSelector:say];
|
76 |
|
77 |
//用函数指针的形式调用setSkinColor
|
78 |
setSkinColor_Func(cattle[1],skin,@ "verbose" );
|
79 |
|
80 |
NSLog (@ "Running as a function pointer will be more efficiency!" );
|
81 |
|
82 |
//调用saySomething方法
|
83 |
say_Func(cattle[1],say);
|
84 |
} |
85 |
86 |
@end |
01 |
#import <Foundation/Foundation.h> |
02 |
#import "DoProxy.h" |
03 |
04 |
int main ( int argc, const char * argv[]) {
|
05 |
NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc] init];
|
06 |
DoProxy *doProxy = [DoProxy new ];
|
07 |
|
08 |
[doProxy setAllIVars];
|
09 |
[doProxy SELFuncs];
|
10 |
[doProxy functionPointers];
|
11 |
|
12 |
[doProxy release];
|
13 |
[pool drain];
|
14 |
return 0;
|
15 |
} |
运行结果:
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.