最新版本的Objective-C和XCode中的(4.4)。
我有一个代码片段,我不明白为什么我能使用一些线路,让我解释一下:
// For understanding purpose : (NSMutableArray*)_programStack
id l_topItemOnStack = [_programStack lastObject];
if([l_topItemOnStack isKindOfClass:[NSNumber class]])
{
return [l_topItemOnStack doubleValue];
}
我的问题:因为我的l_topItemOnStack
是类型的id
,我并没有将它转换成一个NSNumber
,我怎么能使用[l_topItemOnStack doubleValue]
我猜,我不得不首先投来的NSNumber访问NSNumber的方法...
我缺少的是在这里吗?
由于Objective-C是一种动态语言,消息名称和它们的声明只是提示编译器 - 实际信息查找和发送出现在运行时。 所以,即使编译器不知道你的对象响应doubleValue
消息时,它仍然能够使您的通话将
return objc_msgSend(l_topItemOnStack, @selector(doubleValue));
和往常一样。
此外,编译器查找所有已在包括头宣布任何地方的选择,并尝试使用实际上下文来找到最佳匹配-这里的doubleValue是一个独特的名字-它的NSNumber只是声明年代,所以编译器假定您的对象确实是一个NSNumber。
如果你真的想,当你调用的方法或最初宣布它作为一个NSNumber避免这种情况,要么投的对象。
id
代表任何Objective-C类。 这是不一样NSObject *
,因为在这种情况下,你无法使用-doubleValue
方法没有它强制转换为NSNumber
第一。
您可以发送任何消息id
( nil
的类型的id
,太),而无需将其转换为特定的类。 您应该谨慎,不过,作为一个无法识别的选择会导致崩溃。
编辑:
id
是指:一个指针一个未知类的目标C对象
如果您想了解更多关于的区别id
, void *
和NSObject *
你应该阅读这篇博客文章: http://unixjunkie.blogspot.de/2008/03/id-vs-nsobject-vs-id.html
编译器简单地匹配与要翻译(通过可见选择对象#import
)。
如果有仰视选择匹配或消息,如果签名不匹配,并有声明的多重选择器时的不确定性可能抱怨。 在这种情况下,你要么必须把对象:
return [(NSNumber*)l_topItemOnStack doubleValue];
或者将其分配给一个新的变量:
NSNumber * number = l_topItemOnStack;
return [number doubleValue];
为了消除歧义的类型编译器知道正确的选择的签名(这样就可以了,例如,正确设置堆栈)。
在MRC,编译器实际上可以“假设”参数和返回类型(默认为id
) -但在ARC禁止。
首先检查ü是否topItemOnStack是NSNumber的类型为NSNumber的继承NSValue
一个NSValue对象为单C或Objective-C的数据项的简单容器。 它可以容纳任何标量类型,如整数,浮点,和焦炭,以及指针,结构,和对象ID
topItemOnStack can now be of any type floatValue, intValue or doubleValue as per our requirement
通过使用isKindOfClass没有铸造topItemOnStack到NSNumber的,但检查它是否是一个类型的NSNumber的。
isKindOfClass指示接收器是否是给定的类的一个实例或从该类继承的任何类的一个实例
Objective-C的对象具有在捆绑的运行时类型信息(著名的isa
指针)。
您可以发送任何信息的任何对象; 编译器会抱怨(警告),如果它不能找到编译时类型信息,以决定是否将对象响应选择器(在本例doubleValue
),但我相信类型的对象id
,是通用的,不受此规则豁免和任何事情都会发生在编译时( 有人更了解请证实 )。
当然,如果该对象指向由类型ID的变量不执行相应的方法(即,不能对发送的消息进行响应),异常将被抛出。 在iOS系统中,这意味着应用程序崩溃(除非有问题的对象重写了这个默认行为)。 在OS X中,并不总是( 再次,有人更了解请证实 )。