在Objective-C中,与C中的id
完全一样void *
吗?(通用指针类型)。
如果是这样,当我们使用
id obj = [[Fraction alloc] init];
[obj methodName];
obj = [[ComplexNumber alloc] init];
[obj anotherMethodName];
当方法被调用时,程序通过什么方式知道什么是类obj
?
在Objective-C中,与C中的id
完全一样void *
吗?(通用指针类型)。
如果是这样,当我们使用
id obj = [[Fraction alloc] init];
[obj methodName];
obj = [[ComplexNumber alloc] init];
[obj anotherMethodName];
当方法被调用时,程序通过什么方式知道什么是类obj
?
id
与 a 不一样void *
。id
是一个指向未知类型的 Objective C 对象的指针;像object
C# 或 Java 的数据类型。Avoid*
可以指向任何东西;非 nilid
应指向所有 ObjC 对象共有的数据结构,并包含指向其各自类数据的指针。
ObjC 运行时-//etc 的alloc
实现init
。- 确保所有有效对象中都有正确的类指针。
IIRC,在 Apple 的实现中,指向的指针大小的变量实际上是id
指向类的指针。
在类的数据块中,有一个方法列表,将方法签名映射到指向方法实现的函数指针。从那里开始,这是一个相当简单的查找,当您向对象发送消息(即调用其中的方法)时,它会在运行时发生。还有一个指向基类的指针,以便方法查找可以继续沿继承树向上。
顺便说一句,这就是为什么取消引用 void 指针是编译器错误,而将消息发送到 anid
是合法的,如果静态不安全的话。
id
Objective-C 中的内容与 C 中的内容不同void *
。
来自 Apple 的“The Objective-C Programming Language”:
typedef struct objc_object {
Class isa;
} *id;
这意味着,id
是一个指向objc_object
结构的指针,它不同于指向void
.
因此,每个对象都有一个
isa
变量,告诉它它是什么类的实例。由于Class
类型本身被声明为指针。
typedef struct objc_class *Class;
关于,程序如何在方法调用期间告诉类?,这是来自上面引用的同一编程指南:
isa
实例变量标识对象的类——它是什么类型的对象。具有相同行为(方法)和相同类型数据(实例变量)的对象是同一类的成员。因此,对象在运行时是动态类型的。无论何时需要,运行时系统都可以通过询问对象来找到对象所属的确切类。(要了解有关运行时的更多信息,请参阅 Objective-C 运行时编程指南。)
根据指南,id
Objective nil
-C 的 、 和其他基本类型都在头文件中定义objc/objc.h
。
是的,id
只是一个通用指针。编译时的类解析只是为了通知用户警告和错误。但是,具有 id 类型的名副其实在编译时不会绑定到任何特定的类。在运行时访问对象之前,不会知道实际的类。如果对象是 的子类NSObject
,它很可能是,您的代码可以询问对象它的类是什么。
[myObject class]
将返回myObject
. [myObject isMemberOfClass:[SomeClass class]]
将返回一个BOOL
指示更白的 ir 不是myObject
该类的成员SomeClass
。
如果您的代码调用 上的方法myObject
,运行时将尝试进行调用,即使对象没有响应该方法。如果myObject
不实现该方法,则会发生运行时异常。
您也可以myObject
提前询问该方法是否适用于[myObject respondsToSelector:@selector(myCoolMethod)]
.