1

我正在整理一个面试问题列表,供面试成为 Cocoa 开发人员的人使用。我是一名程序员,但我从未做过 Objective-C。我偶然发现了一个涉及动态类型的有趣问题。它应该是基本的,我已经尝试过并编译过它,但我仍然不确定它是如何以及为什么工作的。

问题是

当您执行以下操作时,在编译时和运行时会发生什么:

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

在调试器中我得到

i = (int) 3
s = (__NSFCNumber*) 0x383(无效地址)

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

有人能给我解释一下编译器和运行时系统是如何处理所有这些的,同时还要记住我对 Objective-C 和 Cocoa 完全陌生,但对计算机科学一点也不陌生?

4

3 回答 3

3

您的 s 只是一个标准的 C 指针,NSNumber分配了一个对象(指向 a 的指针)。

NSNumber, 以及NSString, 回应intValue. 就是这样。

于 2011-10-05T16:23:12.320 回答
3

s是您已声明将指向NSString对象的指针。它可以指向任何东西,但理想情况下它应该指向一个 NSString。然而,代码示例s指向一个 NSNumber 对象。

只要您只向s那些NSNumber响应所有内容的方法发送方法就可以了(编译器警告除外)。s如果您尝试向NSNumber指向的对象发送一个 NSString 方法,那么您将得到一个异常。如果对象具有匹配的选择器签名(即:)@selector(intValue),则将调用该方法。

于 2011-10-05T16:23:40.743 回答
3

为变量“s”声明 NSString 仅仅是为了帮助编译器解释变量“s”的意图。它允许编译器在您打算使用某种类型的变量但意外分配了不同类型的变量的情况下强制执行静态类型检查。在 ObjC 中,变量可以指向任何对象,而括号语法是向对象发送“消息”的一种方式。发送消息指示编译器生成查找实现消息的函数的代码。在 ObjectiveC 中,消息也被称为选择器。(低层次的细节稍微多一些,但在高层次上就是这样。)这是动态类型的动态部分,也称为“鸭子打字”。这个想法是,如果它看起来像一只鸭子,你应该能够让它像鸭子一样嘎嘎叫。本质上,任何遵循特定形状的对象都可以分配给适合该形状的类型。

考虑以下:

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

编译器会在此处标记您,表明您打算花时间与狗相处,但实际上是在与猫打交道。然而,这是完全有效的,因为猫的形状类似于狗,因为它们都可以走路和吃准备好的饭菜。Duck typing 可以让您摆脱这种情况,因为在很多情况下您需要接受事先不知道的变量类型。此外,通过自省,您可以在运行时发现对象的形状。如果我们想让我们的小狗吠叫,请考虑上面的代码。我们会得到一个异常,应用程序会崩溃。然而,我们可以使用自省来询问我们的对象是否响应“吠叫”消息以避免崩溃。

if([myPuppy respondsToSelector:@selector(bark)]) {
   [myPuppy bark];
}
于 2011-10-05T16:42:55.063 回答