4

我刚刚发现了一些我有点困惑的事情,不知道是否有人会为我澄清一下。

NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
    NSLog(@"COUNT: %d", [eachObject length]);
}

为什么上述内容没有抱怨/警告我要求 id 的长度这一事实?

4

6 回答 6

5

在 Objective-Cid中,它是任何类型的对象的通用类型,而不管类如何,并且可以用于类的实例和类对象本身。该id类型是完全非限制性的,它没有关于对象的信息,除了它是一个对象。所以编译器无法知道该对象是否可以响应方法,因为它不知道它是什么类型的对象。通过在您的代码中使用它,您基本上是在说“无论它指向什么,执行此操作”。

于 2012-08-01T16:57:10.730 回答
4

编译器永远不会键入发送到 id 的检查消息。这部分是使 Objective-C 充满活力的原因。

如果 eachObject 是任何其他类型,那么如果编译器无法解析方法名称,则会出现错误。

于 2012-08-01T16:52:25.447 回答
4

当您id特别不想进行编译器类型检查时使用。您可以在没有警告的情况下将任何消息发送到id类型,并且可以将 an 分配id给任何其他类型而无需进行类型转换。

这允许您在不使用强制转换的情况下从数组中获取对象。例如,你可以假设数组包含 NSStrings:

NSString* someString = [myArray objectAtIndex:1];

它还允许您在没有强制转换或警告的情况下向对象发送消息。事实上,您希望发送的消息可能不属于任何正式的类或协议:

id someObject = [myArray objectAtIndex:1];
if ([someObject respondsToSelector:@selector(setName:)])
{
    [someObject setName:@"Foo"];
}
于 2012-08-01T17:00:54.550 回答
3

可能包含不同的NSArray对象类型,例如:

NSArray *thArray = [[NSArray alloc] initWithObjects:@"Stack",@"Overflow",[NSNumber numberWithInt:10],nil];
for(id theObject in thArray) {
    NSLog(@"COUNT: %lu", [theObject length]);
}

id可以表示任何对象(在本例中为或NSStringNSNumber
因此编译器无法知道原始方法是否length存在。

于 2012-08-01T16:57:24.630 回答
1

简单地说,id 表示所有 Objective-C 类。所以,它属于一个 NSString 类的长度方法。编译器不会向您发出警告。id 在运行时动态确定,在编译时未知。

于 2012-08-01T16:56:09.917 回答
0

Objective-C 中的每个对象都知道它有什么类以及它是否可以处理消息。检查类的不是编译器,而是运行时的对象本身。

一个对象的类可以在编译时未定义,但在运行时每个对象都有一个已定义的类。

于 2012-08-01T16:54:07.817 回答