头文件:
#import <Foundation/Foundation.h>
#define SET_SKIN_COLOR @"setSkinColor:"
#define BULL_CLASS @"Bull"
#define CATTLE_CLASS @"Cattle"
@interface DoProxy : NSObject {
BOOL notFirstRun;
id cattle[3];
SEL say;
SEL skin;
void(*setSkinColor_Func) (id, SEL, NSString*);
IMP say_Func;
Class bullClass;
}
- (void) doWithCattleId:(id) aCattle colorParam:(NSString*) color;
- (void) setAllIVars;
- (void) SELFuncs;
- (void) functionPointers;
@end
源文件:
1 #import "DoProxy.h"
2 #import "Cattle.h"
3 #import "Bull.h"
4
5 @implementation DoProxy
6 - (void) setAllIVars
7 {
8 cattle[0] = [Cattle new];
9
10 bullClass = NSClassFromString(BULL_CLASS);
11 cattle[1] = [bullClass new];
12 cattle[2] = [bullClass new];
13
14 say = @selector(saySomething);
15 skin = NSSelectorFromString(SET_SKIN_COLOR);
16 }
17 - (void) SELFuncs
18 {
19 [self doWithCattleId:cattle[0] colorParam:@"brown"];
20 [self doWithCattleId:cattle[1] colorParam:@"red"];
21 [self doWithCattleId:cattle[2] colorParam:@"black"];
22 [self doWithCattleId:self colorParam:@"haha"];
23 }
24 - (void) functionPointers
25 {
26 setSkinColor_Func=(void (*)(id, SEL, NSString*)) [cattle[1] methodForSelector:skin];
27 //IMP setSkinColor_Func = [cattle[1] methodForSelector:skin];
28 say_Func = [cattle[1] methodForSelector:say];
29 setSkinColor_Func(cattle[1],skin,@"verbose");
30 NSLog(@"Running as a function pointer will be more efficiency!");
31 say_Func(cattle[1],say);
32 }
33 - (void) doWithCattleId:(id) aCattle colorParam:(NSString*) color
34 {
35 if(notFirstRun == NO)
36 {
37 NSString *myName = NSStringFromSelector(_cmd);
38 NSLog(@"Running in the method of %@", myName);
39 notFirstRun = YES;
40 }
41
42 NSString *cattleParamClassName = [aCattle className];
43 if([cattleParamClassName isEqualToString:BULL_CLASS] ||
44 [cattleParamClassName isEqualToString:CATTLE_CLASS])
45 {
46 [aCattle setLegsCount:4];
47 if([aCattle respondsToSelector:skin])
48 {
49 [aCattle performSelector:skin withObject:color];
50 }
51 else
52 {
53 NSLog(@"Hi, I am a %@, have not setSkinColor!", cattleParamClassName);
54 }
55 [aCattle performSelector:say];
56 }
57 else
58 {
59 NSString *yourClassName = [aCattle className];
60 NSLog(@"Hi, you are a %@, but I like cattle or bull!", yourClassName);
61 }
62 }
63 @end
文件解读:
第10行代码是通过一个预定义的宏BULL_CLASS取得Bull的Class变量。
第11和12行代码是使用bullClass来初始化我们的cattle实例变量数组的第2和第3个元素。
第14行是通过@selector函数来取得saySomething的SEL变量。
第15行是通过向NSSelectorFromString传递预定义的宏SET_SKIN_COLOR来取得setSkinColor的SEL变量。
第22行,笔者打算“戏弄”一下doWithCattleId,向传递了不合适的参数。
第26行,笔者取得了传统的C语言的函数指针,也是使用了第5.5节所述的第一种取得的方法。
第28行,笔者通过5.5节所述的第二种取得的方法得到了函数指针say_Func。
第29行和31行分别执行了分别在第26行和28行取得的函数指针。
第35行是一个BOOL型的实例变量notFirstRun 。当对象被初始化之后,确省的值是NO。第一次执行完毕之后,我们把这个变量设定成为YES,这样就保证了花括号里面的代码只被执行一次。
第37行我们通过_cmd取得了doWithCattleId这个方法名字用于输出。当然同学们在设计方法的提供给别人使用的时候,为了防止使用方法的人把这个方法本身传递进来造成死循环,需要使用_cmd这个系统隐藏的变量判断一下。笔者在这里没有做出判断,这样写从理论上来说存在一定的风险。
第42行,我们通过向对象发送className消息来取得这个对象的类的名字。
第43行和第44行,我们通过NSString的方法isEqualToString来判断取得的类的名字是否在我们事先想象的范围之内,我们只希望接受Bull或者Cattle类的对象。
第46行,本来我们想通过SEL的方式来进行这个牛股的设定,但是由于它的参数不是从NSObject继承下来的,所以我们无法使用。我们会有办法解决这个问题的,我们将在后面的章节里面介绍解决这个问题的方法。
第47行的代码,有一个非常重要NSObject的方法respondsToSelector,通过向对象发送这个消息,加上一个SEL,我们可以知道这个对象是否可以相应这个SEL消息。由于我们的Cattle无法相应setSkinColor消息,所以如果对象是Cattle类生成的话,if语句就是NO所以花括号里面的内容不会得到执行。
第59行,我们通过类的名字发现了一个假冒的Cattle,我们把这个假冒的家伙给揪出来,然后实现了屏幕打印。
结果:
分享到:
相关推荐
Objective-C是基于C语言的,主要用于构建iOS和macOS应用程序,而Objective-C++则是Objective-C的一个扩展,它引入了C++的特性,使得开发者可以同时利用Objective-C的动态特性和C++的面向对象编程能力。 ### ...
用Objective-C语言实现了各种设计模式,收集各种例子,方便大家学习和普及设计模式。.zip用Objective-C语言实现了各种设计模式,收集各种例子,方便大家学习和普及设计模式。.zip用Objective-C语言实现了各种设计...
《Objective-C 程序设计(第4版)》结合独特的学习方法,在每章都编写有大量的小程序例子和练习,使Objective-C程序设计适合于课堂教学和自学。 《Objective-C 程序设计(第4版)》已经为iOS 5和Xcode4.2中的重大...
elcome to Learn Objective- C on the Mac! This book is designed to teach you the basics of the Objective- C language. Objective- C is a superset of C and is the language used by many (if not most) ...
Objective-C是在C语言的基础上扩展了Smalltalk式的面向对象特性,使得它既有C语言的强大功能,又具备了面向对象编程的灵活性。 在Objective-C中,类是所有对象的基础。类定义了一组属性(实例变量)和方法(函数)...
- **文件操作**:Objective-C 提供了读写文件的方法,可能在例子中涉及文件的保存和加载。 - **网络编程**:如何使用 NSURLSession 进行网络请求,或者使用 NSInputStream 和 NSOutputStream 处理流数据。 - **动画...
Objective-C运行时系统(Run time)是Objective-C语言的关键组成部分,它允许许多决策在编译时和链接时推迟到运行时进行。这意味着Objective-C不仅仅是依赖编译器,还需要一个运行时系统来执行编译后的代码。运行时...
Objective-C也支持多线程编程,这在开发高性能的应用程序时非常重要。下面是一个使用`NSThread`进行多线程编程的例子: ```objective-c // 创建一个线程 NSThread *myThread = [[NSThread alloc] initWithTarget:...
Objective-C作为一种成熟的编程语言,为开发者提供了强大的面向对象编程能力,尤其是在苹果生态系统的开发中占据着重要的地位。尽管Swift的出现和发展对Objective-C构成了一定的挑战,但Objective-C依然在很多项目中...
Objective-C是一种强大的面向对象的编程语言,主要应用于Apple的iOS和macOS操作系统。它是由Stepanov和Moss在1983...通过阅读和实践书中的例子,读者将能掌握Objective-C的核心技能,并具备开发iOS和macOS应用的能力。
从C++到Objective-C的转型指南涉及到了几个重要的IT知识领域,主要包括编程语言的比较、面向对象编程的概念、Objective-C语言的语法特点以及与C++的共性和差异。 首先,Objective-C是一种主要在苹果公司产品开发中...
Objective-C是一种基于C语言的扩展,强调动态特性和面向对象设计,是Mac OS X和iOS开发的主要语言。Cocoa是Mac OS X的主要应用框架,包含一系列Objective-C类,用于快速构建功能丰富的OS X应用程序。Apple提供了一套...
由于Objective-C是苹果公司在其操作系统(如macOS和iOS)上开发应用的主要语言之一,因此对于想要从事苹果平台软件开发的开发者来说,掌握Objective-C是非常重要的。 #### 二、Objective-C的基本概念 1. **减号和...
Objective-C是一种强大的面向对象的编程语言,主要用于Apple的iOS和macOS平台开发。它是C语言的一个超集,融入了...通过阅读和实践书中的例子,你将能够熟练掌握Objective-C,并高效地开发iOS和macOS应用程序。
块是Objective-C中一种重要的数据类型,类似于C语言中的函数指针。它们可以被传递给方法或者存储在变量中。例如: ```objective-c void (^myBlock)(void) = ^{ NSLog(@"This is a block!"); }; myBlock(); ``` ##...
本章节可能会通过一个具体的例子来展示如何运用Objective-C进行软件开发,并且会涉及到一些高级话题,如多线程和性能优化等。 最后一章“Après Code: Distributing Your Application”主要讲述了如何发布和分发你...
Objective-C继承了C语言的数据类型,支持诸如`int`、`float`、`char`等基础类型,并且引入了一些高级类型,如`NSString`用于处理字符串。例如: ```objective-c int age = 25; float height = 5.9; char grade = 'A...
Objective-C扩展了C语言,添加了消息传递机制和面向对象特性。消息传递是通过“-”或“+”符号进行的,分别代表实例方法和类方法。例如,你可以向一个对象发送一个消息`[myObject performTask:]`来执行特定的任务。 ...