Objective-C id类型实现原理

在 Objective-C中id类型的对象可以转换为任何一种对象,有点类似与void*指针类型的作用。下面简要介绍一下id类型。

        id标志符:通用对象类型。id类型是一个独特的数据类型,可以转换为任何数据类型,即id类型的变量可以存放任何数据类型的对象。这是为什么呢?还是从OC的内部实现机制上来分析吧!

在内部处理上,id类型被定义为指向对象的指针,这可以从id的定义中看出。id在objc.h中的定义为:

typedef struct objc_object {
    Class isa;
} *id;

而Class为typedef struct objc_class *Class,即Class为struct objc_class的指针别名,而objc_class在runtime.h中的定义为

struct objc_class {
    Class isa;
#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

从上面的代码看出,id是指向objc_object的一个指针。那么它为什么可以指向NSObject对象呢?还是看NSObject的定义吧!

@interface NSObject <NSObject> {
    Class    isa;
}

可以看出NSObject只有一个Class对象isa,而objc_object也是只有一个Class对象isa,可以看成两者等价(不知道对不对?)。所以id是一个一个比较灵活的对象指针,并且是一个指向任何一个继承了Object(或者NSObject)类的对象。而在cocoa的开发环境里,NSObject是所有类的根类。所以id可以指向任何一个cocoa的合法对象。

从上面的代码分析可以看出,id实际上是一个指向NSObjec对象的实例变量的指针,即id和void*并非完全一样。

PS:id和IMP标志符之间的关系:

id:是一种数据类型;

IMP:指向返回id类型值的方法的指针,而且指向的方法带有self和selector对象作为第一个参数。它是一种C类型,可以认为是一种函数指针。其英文解释:IMP is a C type referring to the implementation of a method, also known as an implementation pointer. It‘s a pointer to a function returning id, and with self and a method selector (available inside method definitions as the variable _cmd) as the first arguments。

其使用方法为:id (*IMP)(id, SEL, ...);(SEL为选择器selector的一个类型,选择器就是指向方法的一个指针)

对于NSObject对象,你可以这样来获得一个给定方法的IMP:
IMP imp=[obj methodForSelector:@selector(message)];
对于任意的对象object,
IMP imp=[obj methodFor:@selector(message)];

时间: 2024-11-08 15:55:32

Objective-C id类型实现原理的相关文章

OC基础--构造方法 id类型

new方法实现原理: new做了三件事情 1.开辟存储空间  + alloc 方法 2.初始化所有的属性(成员变量) - init 方法 3.返回对象的地址 [Person new]; == [[Person alloc] init]; alloc: 1.开辟存储空间 2.将所有的属性设置为0 3.返回当前实例对象的地址 init:  1.初始化成员变量, 但是默认情况下init的实现是什么都没有做 2.返回初始化后的实例对象地址 注意: alloc返回的地址, 和init返回的地址是同一个地址

id类型 万能指针 oc

id类型 id已经是关键字,以后定义变量要注意: id是万能指针:能指向.操作任何OC对象,没有*,因为它已经包含了*: Person *p = [Person new];可以用下面的来代替,只适用于OC对象: id d = [Person new]; id 你可以认为是NSObject * 因为NSObject *o = [Person new]; @property id obj;

关于void*类型的用法(相当于OC中的id类型)

关于void*类型的用法(相当于OC中的id类型) 1.C++语言在对于void* 类型的使用很特别,因为void* 可以间接引用任何其他数据类型的指针,比如int*.float*甚至抽象数据类型的指针,而且可以从void* 强制转换为任何其他数据类型的指针,所以使用起来有时候会比较危险.如果开始将一个void*的指针间接引用一个float*的指针,然后将这个void*指针强制转化为一个int*类型的指针,编译器不会给出错误甚至警告,但是输出的数据却匪夷所思,如果再强制转换会float*则不会出

多态、id类型与简单工厂模式

ID类型 objective-c中id可以指向任何对象,在使用id的时候注意:不要再id后面加上'*' . id object = [[Child alloc] init]; // 类型转换 Child *child = (Child *) object ; [child myMethod] ; id 的缺点 id类型所存储的对象到运行时才判断对象所属的类,当我们使用id类型调用一个不存在的方法时,运行之前并不报错,运行起来后程序会崩溃.比如下面这个错误的例子. // animal 没有main

协议和id类型

id类型表示一个可以指向任何类型的对象的指针,它是一个泛型对象类型.你可以将任何对象赋值给一个id类型的变量,也可以将一个id类型的变量赋值给任何类型的对象指针.如果一个用尖括号括起来的协议名称跟随在id之后,则编译器(以及阅读此代码的人)将知道你期望任意类型的对象,只要其遵守该协议.

OC学习笔记 id类型

id是oc语言中一个独特的数据类型.一种通用对象类型.可以转换为任何数据类型,即id类型的变量可以存放任何数据类型的对象. 万能指针,能指向操作任何OC对象 id ==NSObject * 这是为什么呢?还是从OC的内部实现机制上来分析吧! 在内部处理上,id类型被定义为指向对象的指针,这可以从id的定义中看出.id在objc.h中的定义为: 1 typedef struct objc_object { 2 Class isa; 3 } *id; 而Class为typedef struct ob

id类型

id类型 在Objective-C 中,id 类型是一个独特的数据类型.在概念上,类似Java 的Object 类,可以转换为任何数据类型.换句话说,id 类型的变量可以存放任何数据类型的对象.在内部处理上, 这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针. 例如,下面定义了一个id类型的变量和返回一个id类型的方法: id anObject; - (id) newObject: (int) type; id 和void *并非完全一样.下面是id在objc.h中的定义

OC中构造方法、自定义构造方法、id类型

一:id类型 1> id 是一种类型,万能指针,能够指向\操作任何的对象. typedef struct objc_object *id; 注意点:在使用id定义的时候,一定要注意(*)id类型默认已经包含了*所以不需要在加*; 局限性:调用一个不存在的方法,编译器会马上报错. 2>instancetype类型 (1)instancetype会让编译器检查实例化对象的准确类型 (2)instancetype只能用于返回类型,不能当做参数使用 3>.instancetype & i

黑马程序员---OC基础5【点语法】【@property关键字】【@synthesize关键字】【id类型】【动态类型】【构造方法】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [点语法] 1 1.使用“点语法” 2 Student *stu= [[Student alloc]init]; 3         //调用set方法 4         [stu setAge:20]; 5         [stu setName:@"Jone"]; 6         //点语法:xcode的特性,Xcode帮我们做了代码替换 7         //点语法,