2011-10-05 73 views
1

我在爲一個面試人員做一個可可開發人員的面試問題列表。我是一名程序員,但我從未做過Objective-C。我偶然發現了一個涉及動態輸入的interesting question。它應該是初級的,我已經嘗試過並編譯了它,但我仍然不確定它是如何以及爲什麼會起作用的。無法弄清楚這個動態打字的東西

的問題是

當您執行以下在編譯時和運行時會發生什麼:

NSString *s = [NSNumber numberWithInt:3]; 
int i = [s intValue]; 

在調試器中我得到

 
i = (int) 3 
s = (__NSFCNumber*) 0x383 (invalid address) 

的輸出NSLog(@"%d",i)3,輸出NSLog(@"%@",s)3

有人可以給我一個解釋如何通過編譯器和運行時系統處理所有這些,同時也要記住我對Objective-C和Cocoa是全新的,但並不是全新的計算機科學?

回答

3

你的s只是一個標準的C指針,指向一個NSNumber對象(指向a的指針)。

NSNumber以及NSString響應intValue。就是這樣。

+0

關於面試的一面評論:任何一個好的程序員都可以學習任何語言,所以我對理解一個被採訪者的能力比他們的知識更感興趣。我討厭的測試類型問題 - 儘管鏈接中的問題大多是開始交談的好起始點。 –

+0

你最後一句話是我失蹤的。我沒有意識到這兩種類型都會響應'intValue'。 – Phonon

+0

關於面試問題,我完全同意。我通常不會通過給他們測試類型的問題來採訪人們,但我們正在尋找一名iPhone開發人員,公司中沒有人對iPhone編程知道太多,所以我只是試圖看看他們在概念。這就是爲什麼我會訴諸標準化的問答類型的面試,但感謝您的建議。你的觀點非常有效。 – Phonon

3

s是您聲明的指針,它將指向NSString對象。它可以指向任何東西,但理想情況下它應該指向一個NSString。但是,該代碼示例指示s指向一個NSNumber對象。

只要您只發送方法s即方法NSNumber響應一切都很好(可能除了編譯器警告)。如果您要嘗試將NSString方法發送給s所指向的那個NSNumber不響應您的對象,將會發生異常。如果對象具有匹配的選擇器簽名(即:@selector(intValue)),則將調用該方法。

+0

不完全正確,因爲intValue實際上是NSString上的一個方法。最好說NSNumber和NSString都對intValue的簽名(或@selector值)作出響應。 –

+0

你說得對,我已經編輯澄清。謝謝。 – progrmr

3

變量「s」的NSString聲明只是爲了幫助編譯器解釋變量「s」的意圖。它允許編譯器在打算使用某種類型的變量但意外分配了不同類型的變量的情況下強制執行靜態類型檢查。在ObjC中,變量可以指向任何對象,而括號語法是向對象發送「消息」的方法。發送消息指示編譯器生成查找實現消息的函數的代碼。在ObjectiveC消息中也稱爲選擇器。 (低層次的細節稍微有點涉及,但是在高層次,這是它的工作原理。)這是動態類型的動態部分,也被稱爲「鴨子打字」。這個想法是,如果它看起來像一隻鴨子,你應該能夠像鴨子一樣使它嘎嘎。實質上,任何遵循某種形狀的物體都可以指定爲符合形狀的類型。

考慮以下幾點:

Dog *myPuppy = [[Cat alloc] init] autorelease]; 
[myPuppy walk]; 
Food *preparedDish = [self prepareMealForPet]; 
[myPuppy eat: preparedDish]; 

,編譯器將標誌你在這裏說明你打算花時間與狗,但實際上處理的是貓。然而,它是完全有效的,因爲一隻貓的形狀與狗類似,因爲它們都可以步行和吃準備好的食物。由於有很多情況下需要接受事先不知道的變量類型,Duck打字可以讓您避免這種情況。此外通過內省,您可以在運行時發現對象的形狀。考慮上面的代碼,如果我們想問我們的小狗叫。我們會得到一個異常,該應用程序會崩潰。但是,我們可以使用自省來詢問我們的對象是否響應「樹皮」消息以避免崩潰。

if([myPuppy respondsToSelector:@selector(bark)]) { 
    [myPuppy bark]; 
}