C的動態(tài)類型檢查
這次美國之行的一大收獲就是終于正視了Objective-C而不再只是當(dāng)它是不順手的工具了。這主要是有機會拜讀了Brad Cox的《Objective-Oriented Programming, an evolutionary approach》。今天就談?wù)勊?1頁提到的那個極少C程序員甚至C編譯器作者知道的一個極為餛飩的語法:
- struct MYSTRUCT someVariables;
- someVariable = (*((struct MYSTRUCT *)(*)() _msg))(someObject, …);
C語言是靜態(tài)類型檢查的編譯語言.例如下面程序定義和使用了兩個類型:浮點和定點。
- #include <stdio.h>
- typedef struct {
- float x, y;
- } FloatingPoint;
- typedef struct {
- int x, y;
- int scale;
- } FixedPoint;
- int main() {
- FloatingPoint flo;
- FixedPoint fix;
- printf("(%f,%f)\n", flo.x, flo.y);
- printf("(%f, %f)\n", 1.0*fix.x/fix.scale, 1.0*fix.y/fix.scale);
- }
不同類型間的轉(zhuǎn)換需要cast,否則編譯時會被警告。后門還是有的,就是void *類型。我們聲明id是此void *類型,加入一個使用它的迷你函數(shù):
- typedef void *id;
- id thePoint(id thePoint) {
- return thePoint;
- }
這樣在main里我們可以使用明確的類型轉(zhuǎn)換,不會被警告:
- id flid = thePoint(&flo);
- printf("(%f,%f)\n", ((FloatingPoint *)flid)->x, ((FloatingPoint *)flid)->y);
但類型錯了也沒了警示報告:
- FloatingPoint *flip = thePoint(&fix);
- printf("(%f,%f)\n", flip->x, flip->y);
我們試著改寫為間接的函數(shù)指針類型,當(dāng)然也沒有編譯預(yù)警:
- id (*thePointPointer)(id);
- thePointPointer = &thePoint;
- flip = thePointPointer(&fix);
- printf("(%f,%f)\n", flip->x, flip->y);
但如果我們加入明確類型,就會看到預(yù)期的警示,雖然是有些啰嗦:
- FloatingPoint *(*theFloatingPointPointer)(FloatingPoint *);
- theFloatingPointPointer = &thePoint;
- flip = theFloatingPointPointer(&fix);
- printf("(%f,%f)\n", flip->x, flip->y);
但這很容易解決,寫在一行就行了:
- FloatingPoint *flop = ((FloatingPoint *(*)(FloatingPoint *))&thePoint)(&fix);
我想這就是書中提到的意思。Objective-C是超級的C語言,這些餛飩都被精心的包裝成了簡潔的語法。帶類型檢查的動態(tài)語言 —— 我喜歡。