我刚刚发现了一些我有点困惑的事情,我想知道是否会有人为我澄清它。
NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
NSLog(@"COUNT: %d", [eachObject length]);
}
为什么上面没有抱怨/警告我要求身份证的长度?
答案 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
可以代表任何对象(在这种情况下为NSString
或NSNumber
),
因此编译器无法知道原始方法length
是否存在。
答案 4 :(得分:1)
简单地说,id表示所有Objective-C Class。所以,length方法它属于NSString类。编译器没有向您发出警告。 id在运行时动态确定,在编译时未知。
答案 5 :(得分:0)
Objective-C中的每个对象都知道它具有哪个类以及它是否可以处理消息。检查类的编译器不是,它是运行时的对象本身。
对象的类可以在compilertime中未定义,但在运行时,每个对象都有一个已定义的类。