2011-10-20 37 views
2

偶爾,開發/調試過程中,我希望確保對象是某一類型:嚴格的類型檢查在Objective-C通過宏

PageTopBottom *newPage = [notification object]; 
assert([newPage isKindOfClass:[PageTopBottom class]]); 

我已經工作到這個

#define assertType(_var_, _class_) assert([_var_ isKindOfClass:[_class_ class]]) 

PageTopBottom *newPage = (id)[notification object]; 
assertType(newPage, PageTopBottom); 

,但現在我想,如果可能的話,只需要使用

assertType(newPage) 

是否有可能從變量中獲取有關變量聲明類型的信息?

我不是很積極,我正確地構思了問題,但任何答案讓我能夠assertType與一個參數將是偉大的。

回答

4

是否有可能獲得有關信息變量的變量的聲明類型?

不。在程序運行時,該信息將丟失。在你的情況下,newPage只是一個32位或64位的數字,指向一小部分含有Objective-C對象的內存。

我覺得你原來unmacro'd版本是在這裏做正確的事情:

assert([newPage isKindOfClass:[PageTopBottom class]]); 

,完美記錄了你正在即假設你承擔NEWPAGE是PageTopBottom的實例或它的一個子對於瞭解Objective-C的人來說,這是完全清楚的。你的宏版本稍微模糊了一點,因爲在代碼中碰到它的人可能會相信它是斷言newPage是一個PageTopBottom而不是它的一個子類(你可以改變宏的名字來防止這種情況,但我想只是不會打擾)。

編輯

你可以做的是聯合聲明,並斷言在一個:

#define DECLARE_AND_ASSERT_IS_KIND_OF_CLASS(T, V, I) T* V = (T*)(I); assert([(V) isKindOfClass: [(T) class]) 

這將這樣的工作:

DECLARE_AND_ASSERT_IS_KIND_OF_CLASS(PageTopBottom, newPage, [notification object]); 
+0

太棒了,謝謝。我現在至少會將我的宏更改爲「ASSERT_IS_KIND_OF_CLASS」。如果可能的話,我不想混淆該聲明,因爲一旦不再需要聲明,我將刪除它。 –

+0

嗨,讓我知道如果你認爲我應該打開一個單獨的問題:如果問題是比較參數和方法的簽名怎麼辦?換句話說,做一個嚴格的打字參數檢查... –

+0

@Yar:是的,單獨的問題,我認爲。 – JeremyP

1

預處理器只處理文本;它沒有類型知識,這就是爲什麼它有時被認爲是「危險的」。我能看到的唯一方法是將變量聲明包裝在一個宏中,我強烈建議不要,並且可能不會真正減少代碼或複雜性。

另外,你不應該在鑄造之前檢查型號嗎?

+0

我不知道它的事項無論你在演員之前還是演員之後聲稱,因爲你會炸燬無論:)謝謝@ –

1

嗯,與目標C++有兩種選擇:

  1. 寫模板函數

    模板空隙assertType(T * OBJ){...}

  2. 對於指針X* x,使用NSClassFromString([NSString stringWithUTF8String:typeid(*x).name()])

不使用C++,你可能能夠使用GCC擴展typeof,但我不知道,如果[typeof(*x) class]是一個合法的操作...

+0

謝謝@Yuji。我不確定這是否正確,但問題是關於objective-c。我可以混合? –

+0

是的,只需將文件擴展名改爲'.mm'而不是'.m'。然後你可以混合使用Objective-C和C++。這不是說兩個系統是統一的......只是你可以同時使用兩個系統。 – Yuji