我刚刚发现了一些我有点困惑的事情,不知道是否有人会为我澄清一下。
NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
NSLog(@"COUNT: %d", [eachObject length]);
}
为什么上述内容没有抱怨/警告我要求 id 的长度这一事实?
我刚刚发现了一些我有点困惑的事情,不知道是否有人会为我澄清一下。
NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
NSLog(@"COUNT: %d", [eachObject length]);
}
为什么上述内容没有抱怨/警告我要求 id 的长度这一事实?
在 Objective-Cid
中,它是任何类型的对象的通用类型,而不管类如何,并且可以用于类的实例和类对象本身。该id
类型是完全非限制性的,它没有关于对象的信息,除了它是一个对象。所以编译器无法知道该对象是否可以响应方法,因为它不知道它是什么类型的对象。通过在您的代码中使用它,您基本上是在说“无论它指向什么,执行此操作”。
编译器永远不会键入发送到 id 的检查消息。这部分是使 Objective-C 充满活力的原因。
如果 eachObject 是任何其他类型,那么如果编译器无法解析方法名称,则会出现错误。
当您id
特别不想进行编译器类型检查时使用。您可以在没有警告的情况下将任何消息发送到id
类型,并且可以将 an 分配id
给任何其他类型而无需进行类型转换。
这允许您在不使用强制转换的情况下从数组中获取对象。例如,你可以假设数组包含 NSStrings:
NSString* someString = [myArray objectAtIndex:1];
它还允许您在没有强制转换或警告的情况下向对象发送消息。事实上,您希望发送的消息可能不属于任何正式的类或协议:
id someObject = [myArray objectAtIndex:1];
if ([someObject respondsToSelector:@selector(setName:)])
{
[someObject setName:@"Foo"];
}
可能包含不同的NSArray
对象类型,例如:
NSArray *thArray = [[NSArray alloc] initWithObjects:@"Stack",@"Overflow",[NSNumber numberWithInt:10],nil];
for(id theObject in thArray) {
NSLog(@"COUNT: %lu", [theObject length]);
}
id
可以表示任何对象(在本例中为或NSString
)NSNumber
,
因此编译器无法知道原始方法是否length
存在。
简单地说,id 表示所有 Objective-C 类。所以,它属于一个 NSString 类的长度方法。编译器不会向您发出警告。id 在运行时动态确定,在编译时未知。
Objective-C 中的每个对象都知道它有什么类以及它是否可以处理消息。检查类的不是编译器,而是运行时的对象本身。
一个对象的类可以在编译时未定义,但在运行时每个对象都有一个已定义的类。