没有警告id?

时间:2012-08-01 16:48:01

标签: iphone objective-c xcode cocoa-touch

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

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

为什么上面没有抱怨/警告我要求身份证的长度?

6 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:4)

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

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

答案 2 :(得分:4)

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

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

NSString* someString = [myArray objectAtIndex:1];

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

id someObject = [myArray objectAtIndex:1];
if ([someObject respondsToSelector:@selector(setName:)])
{
    [someObject setName:@"Foo"];
}

答案 3 :(得分: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是否存在。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

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