使用id 这个泛型对象,假如别人传递给你一个id,你如何动态判断这个在
运行时传递过来的对象到底有没有XXX()方法呢?因为id 可以代表任意对象,你也不知道运
行时传递的这个id 里面到底有什么东西。其实NSObject中有一系列这样的方法用于动态判
定,类似于JAVA的反射机制,但是Objective-C的用起来更为简单。
01 | -( BOOL ) isMemberOfClass: (Class) clazz |
04 | -( BOOL ) isKindOfClass: (Class) clazz |
07 | -( BOOL ) respondsToSelector: (SEL) selector |
10 | +( BOOL ) instancesRespondToSelector: (SEL) selector |
13 | - (id) performSelector: (SEL) selector |
上面的后三个方法中都涉及到了一个新类型选择器SEL,它用于表示Objective-C的一个方法,
我们知道在C语言中有函数指针指向一个函数,也就是Objective-C的选择器就相当于C语
言中的函数指针,只不过选择器只能表示Objective-C类型中定义的方法。选择器使用
@selector(方法名)的形式获取,例如:@selector(initWithWidth:andHeight:) 、
@selector(alloc)。同时,SEL是在继Class、id 之后第三个不需要在变量前使用*的类型,
因为它已经是一个指针。
另外,注意上面的红色文字,你可以看到这两行的方法都是-开头的,也就是成员方法,但
是为什么类也可以去掉用呢?其实是类的Class对象去掉用的,因为Class对象有着两个方法
的回应能力。
我们以矩形、正方形的程序为基础,进行代码演示。
01 | int main( int argc, const char *argv[]){ |
02 | MyRectangle *rec=[[MyRectangle alloc] initWithWidth: 2 andHeight: 5]; |
04 | MySquare *squa=[[MySquare alloc] initWithSize: 6]; |
08 | if ([squa isMemberOfClass: [MyRectangle class ]]){ |
09 | printf ( "squa isMemberOfClass MyRectangle\n" ); |
11 | printf ( "squa not isMemberOfClass MyRectangle\n" ); |
14 | if ([squa isMemberOfClass: [MySquare class ]]){ |
15 | printf ( "squa isMemberOfClass MySquare\n" ); |
17 | printf ( "squa not isMemberOfClass MySquare\n" ); |
19 | printf ( "----------------------------------------------\n" ); |
22 | if ([squa isKindOfClass: [MyRectangle class ]]){ |
23 | printf ( "squa isKindOfClass MyRectangle\n" ); |
25 | printf ( "squa not isKindOfClass MyRectangle\n" ); |
28 | if ([squa isKindOfClass: [MySquare class ]]){ |
29 | printf ( "squa isKindOfClass MySquare\n" ); |
31 | printf ( "squa not isKindOfClass MySquare\n" ); |
33 | printf ( "----------------------------------------------\n" ); |
37 | if ([squa respondsToSelector: @selector(initWithSize:)]){ |
38 | printf ( "squa respondsToSelector initWithSize:\n" ); |
40 | printf ( "squa not respondsToSelector initWithSize:\n" ); |
43 | if ([MySquare respondsToSelector: @selector(alloc)]){ |
44 | printf ( "MySquare respondsToSelector alloc\n" ); |
46 | printf ( "MySquare not respondsToSelector alloc\n" ); |
49 | if ([rec respondsToSelector: @selector(initWithWidth:andHeight:)]){ |
50 | printf ( "rec respondsToSelector initWithWidth:andHeight:\n" ); |
52 | printf ( "rec not respondsToSelector initWithWidth:andHeight:\n" ); |
54 | printf ( "----------------------------------------------\n" ); |
57 | if ([MySquare instancesRespondToSelector: @selector(initWithSize:)]){ |
58 | printf ( "MySquare instancesRespondToSelector initWithSize:\n" ); |
60 | printf ( "MySquare not instancesRespondToSelector initWithSize:\n" ); |
63 | if ([MySquare instancesRespondToSelector: @selector(alloc)]){ |
64 | printf ( "MySquare instancesRespondToSelector alloc\n" ); |
66 | printf ( "MySquare not instancesRespondToSelector alloc\n" ); |
68 | printf ( "----------------------------------------------\n" ); |
71 | id x_id=[rec performSelector: @selector(area)]; |
72 | [MyRectangle performSelector: @selector(alloc)]; |