Objective-C:动态绑定是否改变了变量的声明类类型?

时间:2014-03-21 08:10:03

标签: objective-c casting dynamic-binding

我是objective-c的新手。我刚刚学习了如何使用id并编写了以下代码:

NSString *str = @"x";
id obj = str;
NSArray *arr = obj;
NSLog(@"%@, %@\n", str.className, arr.className);

在Xcode中执行,输出为__NSCFConstantString, __NSCFConstantString,没有任何警告。有人可能会告诉我为什么会发生这种情况,因为arr最初被声明为NSArray

我还尝试直接将arr分配给str,如下所示:

NSString *str = @"x";
NSArray *arr = str;
NSLog(@"%@, %@\n", str.className, arr.className);

虽然在xcode中引发了警告,但它可以成功执行并且输出相同__NSCFConstantString, __NSCFConstantString。为什么呢?

我花了很长时间在互联网上搜索,但没有找到一个好的答案。请帮忙!谢谢!

2 个答案:

答案 0 :(得分:2)

在这两种情况下,strarr都是指向同一对象的指针。

Objective-C方法在运行时解析,str.className是一个快捷方式 [str className],表示

  

className消息发送到str指向的对象。

因此str.classNamearr.className会调用相同的方法 同样的例子。

指针的声明类型(NSString *NSArray *)不用于该方法 解析度。你甚至可以打电话给

[obj className];

使用id obj

在第二种情况下,编译器可以警告您不同类型的分配 指针。在第一种情况下这是不可能的,因为id是一个通用指针 可以转换为任何Objective-C指针(与C语言中的void *类似)。

答案 1 :(得分:1)

您只创建了一个类的一个对象。请参阅代码的两个部分:

  1. 对象的实际实例

    在您的情况下,您实际创建对象的唯一时间是您编写@“x”时。

  2. 指向这些对象的指针(包含内存地址的变量)

  3. 当你说

    NSString* str
    

    NSArray* arr
    

    id obj
    

    你正在做的就是创建一个指针变量。在引擎盖下,指针变量只是一个可以保存数字的变量。像一个int。只是它旨在包含对象的内存地址。您可以将指针变量看作餐巾纸,有人从平房的街道地址写下建筑物编号。

    然后你要拿第二张(和第三张)餐巾纸并在上面写上相同的楼号。然而,餐巾纸'arr'实际上是在说它是一栋公寓楼(NSArray),而不是在餐巾纸上注明它是一个平房。在'obj'餐巾纸上,你甚至不打算写它是什么(id)。

    只是因为你的餐巾纸说这个地址是指公寓不会改变你街道上那个号码的房子。

    您为指针变量提供的类型仅仅是对编译器的提示,因此当您意外混淆对象时,它可以发出警告。当您在不同类型的指针变量中写入地址时,不会执行从一种对象类型到另一种对象类型的转换。通常,如果将一种类型的对象的地址分配给另一种类型的指针变量,则会收到错误消息。但是,既然你要通过“obj”变量(类型为“id”),你就会绕过这个检查。 'id'用于你所关心的只是你正在处理一个物体的情况。

    E.g。 NSArray保留任何类型的对象列表,但并不真正关心哪种类型。所以它使用'id'作为它保留的地址类型。这样,你只需要一个数组类,而不是一个NSStringArray,另一个NSNumberArray等。为了使这样的情况更方便,只要涉及'id'变量,编译器就不会发出警告并假设你知道你是什么做。