Objective-C FAQ 中文版(轉貼)

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章