Objective-C FAQ
编辑:David Stes ( [email protected]) 发表:2003年1月28日 翻译者:jeff_yecn 目录 * 目录 * 1. 关于本FAQ + 1.1 我在哪里可以找到本FAQ的最新版本? * 2. Objective-C 编译器指令 + 2.1 Objective-C 源程序的文件后缀是什么? + 2.2 我怎么用Stepstone编译器编译.m文件? + 2.3 我怎么用苹果编译器编译.m文件? + 2.4 我怎么用GNU C编译器编译.m文件? + 2.5 我怎么用POC编译器编译.m文件? * 3. Objective-C 预处理器问题 + 3.1 注释语句的语法是什么? + 3.2 我怎么包含根类 + 3.3 什么是#import + 3.4 为什么要教我使用#import? * 4. 对象的数据类型(id) + 4.1 什么是id + 4.2 self和super有什么不同? + 4.3 什么是@defs( )? * 5 消息选择器(SEL) + 5.1 什么是SEL? + 5.2 perform: 有什么用处? + 5.3 我怎么知道给定method的SEL? * 6. 实现指针(IMP) + 6.1 什么是IMP? + 6.2 怎么通过给定的SEL获得IMP? + 6.3 怎么通过给定的IMP发送消息? + 6.4 怎么将IMP用于要返回双精度浮点数的method? + 6.5 对一个返回双精度浮点数的method,可以用perform: 吗? * 7. 复制对象 + 7.1 copy和deepcopy有什么区别? * 8. Objective-C和C++ + 8.1 怎么把一个C++库连接到Objective-C程序中? * 9. 消息 + 9.1 我怎么产生一个静态的method? + 9.2 我怎么阻止一个对象发送某个消息? + 9.3 如果我更改了一个method的实现,怎么对所有代码进行重新编译? * 10. 实例和类变量 + 10.1 如果我对一个类的实例变量进行了改变的话,我需要对所有代码进行重新编译吗? * 11. Objective-C和X-Windows + 11.1 我怎么把X Intrinsic头文件包含到Objective-C文件中? * 12. Stepstone专有问题 + 12.1 我怎么在栈中分配对象? * 13. GNU Objective-C专有问题 + 13.1 为什么我会得到一个“浮点例外”错误? * 14. 苹果Objective-C专有问题 + 14.1 什么是字符串常量的类? + 14.2 我怎么把C++库与Objective-C程序连接? * 15. 可移植对象编译器(POC)专有问题 + 15.1 类变量的语法是什么? + 15.2 怎么转发消息? + 15.3 我怎么把C++库与Objective-C程序连接? * 16. 书籍和进一步阅读材料 + 16.1 Object-Oriented Programming : An Evolutionary Approach, 2nd Ed. + 16.2 An Introduction To Object-Oriented Programming, 2nd Ed. + 16.3 Objective-C : Object-Oriented Programming Techniques + 16.4 Applications of Object-Oriented Programming; C++ SmallTalk Actor Objective-C Object PASCAL 1. 关于本FAQ 1.1 我在哪里可以找到本FAQ的最新版本? 它每月会在comp.lang.objective-c,comp.answers和news.answers。 同时会归档在ftp://rtfm.mit.edu/pub/faqs/computer-lang/Objective-C/faq。 2. Objective-C 编译器指令 2.1 Objective-C 源程序的文件后缀是什么? 实施文件(implementation file)的后缀是.m,头文件的后缀是.h。Objective-C编译器通常也接受.c作为后缀,但是仅把这些文件按照普通C语言的模式进行编译。 2.2 我怎么用Stepstone编译器编译.m文件? objcc -c class.m objcc -o class class.o 详细信息请参见http://www.stepstn.com 2.3 我怎么用苹果编译器编译.m文件? cc -c class.m cc -o class class.o 详细信息请参见http://www.apple.com 2.4 我怎么用GNU C编译器编译.m文件? gcc -c class.m gcc -o class class.o -lobjc -lpthread 2.5 我怎么用POC编译器编译.m文件? objc -c class.m objc -o class class.o -lobjc -lpthread 3. Objective-C 预处理器问题 3.1 注释语句的语法是什么? Objective-C的预处理器通常支持两类注释: // 这是BCPL风格的注释(有效到本行的末尾) 和 /* 这是C风格的注释 */ 3.2 我怎么包含根类(include the root class) 对stepstone和POC,头文件可以这样包含: 对GNU cc和苹果cc,则: 对Stepstone编译器,根类位于一个叫做runtime的目录中,而对POC编译器,则位于一个叫objcrt的目录里。但由于隐含调用的-I参数传递了给预处理器,上述位置会被自动搜索。 3.3 什么是#import 这是一个C预处理指令,避免同一个文件被多次包含。 #import 相当于: #include 如果这个.h文件能够用下面的办法保护自己避免被重复包含 #ifndef _OBJECT_H_ ... #define _OBJECT_H_ #endif 3.4 为什么要教我使用#import? 由于发现有些人用不好的风格来使用#import,GNU Objective-C编译器会在你使用#import时发送一个错误信息。你可以通过-Wno-import选项来关闭这个警告信息。你也可以通过修改编译器源代码,设置warn_import变量(在文件cccp.c)中。你也可以想上一个问题那样,把你的代码改为使用#ifndef和#endif对,使得你的代码可以运行在所有编译器上。 4. 对象的数据类型(id) 4.1 什么是id 它是Objective-C对各种对象使用的一个通用的C数据类型。例如,一个静态函数,参数为一个对象,返回值也是一个对象,可以这样声明: static id myfunction(id argument) {...} 4.2 self和super有什么不同? self是在method的实现中的一个变量,它表示接收消息的对象。super表示同样的变量,但要求编译器使用其超类(superclass,姑且这么翻译,指当前类所继承的一系列类)中的一个method实现。 如果使用伪码的话,假设copy (from super) 是调用超类中copy这个实现的语法,那么下面两条语句是等价的: myObject = [super copy]; 和 myObject = [self copy (from super)]; //伪码 4.3 什么是@defs( )? 这是一个编译器指令,作用是访问某一个类的实例的内部存储结构。 typedef struct { @defs(MyClass) } *TMyClass; 定义了一个叫TMyClass的C类型,它的存储结构与MyClass实例是完全一样的。 5 消息选择器(SEL) 5.1 什么是SEL? 这是消息选择器对应的C类型。它通常定义为唯一的字符串(method的名字,包括冒号)。但也并非所有的编译器都是这样定义的。 5.2 perform: 有什么用处? perform: 是一个消息,它要求给一个对象发送一条由它的消息选择器(SEL)指定的消息。 5.3 我怎么知道给定method的SEL? 如果method的名字在编译时已经知道,使用@selector: [myObject perform: @selector(close)]; 如果是在运行时,你可以通过一个以消息名为参数的运行时函数获得消息选择器,例如: SEL mySel = selUid(name); //对Stepstone编译器 SEL mySel = sel_getUid(name); //对苹果编译器 SEL mySel = sel_get_any_uid(name); //对GNU Objective-C编译器 SEL mySel = selUid(name); //对POC编译器 6. 实现指针(IMP) 6.1 什么是IMP? 它是method的实现指针的C类型。一个指向实现Objective-C的method的函数的指针。它被定义为返回id类型,并有两个隐含参数,self和_cmd: typedef id (*IMP) (id self, SEL _cmd, ...); 6.2 怎么通过给定的SEL获得IMP? 可以通过发送一个methodFor: 消息完成: IMP myImp = [myObject methodFor: mySel]; 6.3 怎么通过给定的IMP发送消息? 通过重设函数指针。下面的语句是等价的: [myObject myMessage]; 或 IMP myImp = [myObject methodFor: @selector(myMessage)]; myImp(myObject, @selector(myMessage)]; 或 [myObject perform: @selector(myMessage)]; 6.4 怎么将IMP用于要返回双精度浮点数的method? 对返回值不是id而是象双精度浮点数这样的C类型的method,需要将IMP函数指针从返回id的函数强制转换成返回双精度浮点数的函数: double aDouble = ((double (*) (id, SEL))myImp)(self, _cmd); 6.5 对一个返回双精度浮点数的method,可以用perform: 吗? 不行。perform: 这种method是用于发送不含其它参数的返回id类型的消息的。如果消息返回id类型,但有一个其它参数,使用perform: with: 。如果是任意参数数目和任意返回类型的普遍情况,使用methodFor: 。 7. 复制对象 7.1 copy和deepcopy有什么区别? copy是对对象的字节拷贝,与原有对象共享指针,可以被重载以拷贝附加的内存。deepcopy是建立一个不共享指针的拷贝。一个对象的deepcopy包括它的实例变量的拷贝,而一般的复制则通常只包括第一层的拷贝。 8. Objective-C和C++ 8.1 怎么把一个C++库连接到Objective-C程序中? 你可以有两个选择:使用苹果编译器或POC。前者接受C++和Objective-C的混合语法(称做Objective-C++)。后者把Objective-C代码先编译成C,在用C++编译器对中间代码进行编译。详细信息请参见编译器专有问题的解答。(译注:14,15章) 9. 消息 9.1 我怎么产生一个静态的method? method在Objective-C中总是以静态函数的形式实现的。但获得一个method的IMP(实现指针)的唯一方法只能是通过运行时消息(通过methodFor: 和friends),因为对于实现method的文件来说,函数本身是静态的。 9.2 我怎么阻止一个对象发送某个消息? 你不可以。如果你的对象能够响应一个消息,那么其他类就可以发送这个消息。你可以增加一个额外的sender参数来进行检查,例如: - mymethod: sender { if ([sender isKindOf: ...]) ... } 但这仍然要求发送方使用正确的参数以进行配合: [anObject mymethod: self]; 9.3 如果我更改了一个method的实现,怎么对所有代码进行重新编译? 不,你仅需要对更改了代码的文件本身重新编译就可以了。仅仅是发送特定消息的文件是不需要重新编译的,因为Objective-C使用动态绑定。 10. 实例和类变量 10.1 如果我对一个类的实例变量进行了改变的话,我需要对所有代码进行重新编译吗? 你需要对那个类,和它的所有子类,和那些使用@defs或对那个类的实例变量进行直接访问的文件进行重新编译。简而言之,使用@defs来访问实例变量,或通过子类来访问实例变量,破坏了Objective-C通常提供给其他文件(那些你不需要重新编译的文件)的封装。 11. Objective-C和X-Windows 11.1 我怎么把X Intrinsic头文件包含到Objective-C文件中? 为避免Objective-C对象和X11对象的冲突,请参考下面的代码: #include #define Object XtObject #include #include #undef Object 12. Stepstone专有问题 12.1 我怎么在栈中分配对象? 要在栈中分配“MyClass”的一个实例: MyClass aClass = [MyClass new]; 13. GNU Objective-C专有问题 13.1 为什么我会得到一个“浮点例外(floating point exception)”错误? 这常在某些平台上发生,并在ftp://ftp.ics.ele.tue.nl/pub/users/tiggr/objc/README.387中描述过。一个解决方案是在命令行添加-lieee参数,使得在运行时一个非法浮点操作不传送错误信息。DJGPP用户可以参考http://www.delorie.com/djgpp/v2faq/。AIX用户可以参考http://world.std.com/~gsk/oc-rs6000-problems.html。某些情况下,你也可以通过升级到更新版本的GNU Objective-C运行时库和/或编译器来解决这个问题。 14. 苹果Objective-C专有问题 14.1 什么是字符串常量的类? 它是NXConstantString。 NXConstantString *myString = @ "my string"; 14.2 我怎么把C++库与Objective-C程序连接? c++ -c file.m c++ file.o -lcpluslib -o myprogram 15. 可移植对象编译器(POC, Portable Object Compiler)专有问题 15.1 类变量的语法是什么? 把类变量列在实例变量的后面,并和实例变量一样组织在一起,如下: @implementation MyClass : Object { id ivar1; int ivar2; } : { id cvar1; } @end 15.2 怎么转发消息? 应该通过实现doesNotUnderstand: 来发送sentTo: 消息。 - doesNotUnderstand : aMsg { return [aMsg sentTo: aProxy]; } 15.3 我怎么把C++库与Objective-C程序连接? objc -c -cplus file.m objc -cplus file.o -lcpluslib -o myprogram 16. 书籍和进一步阅读材料 16.1 Object-Oriented Programming : An Evolutionary Approach, 2nd Ed. Brad Cox & Andy Novobilski, ISBN 0201548348. 16.2 An Introduction To Object-Oriented Programming, 2nd Ed. Timothy Budd, ISBN 0201824191 16.3 Objective-C : Object-Oriented Programming Techniques Pinson, Lewis J. / Wiener, Richard S., ISBN 0201508281 16.4 Applications of Object-Oriented Programming; C++ SmallTalk Actor Objective-C Object PASCAL Pinson, Lewis J. / Wiener, Richard S., ISBN 0201503697 |