Objective-C对象类型(它是一个结构,对吗?)如何也是一个类(它是一个结构*)?
消息传递括号中的NSObject
实际上是objc_class
结构,它有一个指向元类的指针,其中存储了类方法吗?如果是这样,同一个术语如何也可以作为分配给anObject
的类型?
如:NSObject * anObject = [NSObject alloc] init];
答案 0 :(得分:0)
你可能在想这个;它取决于语言的定义。语言可以在不同的上下文中使用相同的语法元素来表示不同的语义。
子表达式:
[NSObject alloc]
表示“将alloc
消息发送到类型NSObject
的类对象。所以NSObject
用于标识类对象。而声明:
NSObject *anObject;
表示“分配正确大小的变量以保存NSObject *
类型的值,并为其指定名称anObject
。因此NSObject
用于标识类型。< / p>
这两种用法显然密切相关,因此使用类似的语法元素,但它们具有不同的语义。
HTH
附录
如果有帮助,声明:
NSObject *anObject = [[NSObject alloc] init];
根据定义,大致相当于:。
Class objectClass = objc_getClass("NSObject");
NSObject *anObject = [[objectClass alloc] init];
但是使用额外的语言规范/编译时,要求NSObject
必须是可访问类型而不仅仅是字符串中的字符("NSObject"
)。
答案 1 :(得分:0)
Objective-C对象不一定是struct
。曾几何时他们(大部分)都是,但至少从十多年前的Objective-C 2.0开始,他们不可能。
最明显的例子:nil
对象。它是一个接受任何消息并返回nil
的对象。它不是结构。它在内存中不存在。
第二个最明显的例子:在64位运行时中,存储在标记指针中的任何东西都不是结构,因为表面上指针实际上并不指向任何东西。它是对象的价值。堆上没有任何东西。
存在各种其他例子;但是,除非你想要非常广泛地定义一个结构,以及任何意味着某些东西的位集合,否则对象不一定是结构。
NSObject
中的[[NSObject alloc] init]
是对NSObject
的元类的单个实例的引用,它在内存中有某个表示。与任何其他对全局的引用一样,它将在您的二进制文件中存根,通常,实际地址将被动态链接器替换。
假设强联动和/或找到符号。如果你的链接很弱,那么如果没有NSObject
,链接器就会放在对nil
对象的引用中。
您可以同样执行[[NSClassFromString(@"NSObject") alloc] init]
,但效果略有不同:将尝试在运行时查找元类。因此,这不是编译器通常会生成的内容,但是由于运行时成本较低,它将允许继续发送消息,就像您静态地命名该类并进行弱链接一样。
答案 2 :(得分:0)
基本上,Objective-C中的括号语法有两个独立的语法案例:
[<expression> <selector and arguments>]
[<class name> <selector and arguments>]
虽然你可以[NSObject alloc]
,但像NSObject
这样的类名在Objective-C中不是表达式 - 试图使用NSObject
就好像它是其他地方的表达式一样在代码中会产生错误(这就是为什么当我们需要一个表达式来计算类对象的指针时,我们被迫写[NSObject class]
的原因。相反,当你编写[NSObject alloc]
时,它正在使用括号语法的第二种情况,其中前面的东西是类名,而不是表达式。
你可以想象当编译器编译括号语法的第二种情况时会发生什么,例如[NSObject alloc]
它会将它转换为括号语法的第一种情况,但是对于表达式,它使用内部指针NSObject
类对象,有点像[objc_getClass("NSObject") alloc]
,除了它不需要运行时查找,它在编译时直接链接值。
(顺便说一句,在Smalltalk,这是Objective-C的对象系统派生的地方,类名是一个表达式(评估为类对象),所以在Smalltalk中发送消息的语法(除了没有括号几乎与Objective-C相同)并不需要上面两个独立的情况 - 第一个案例已经覆盖了第二个案例。我相信他们并不想要在创建Objective-C时创建类名表达式,因为具有相同的标识符既是类型又是表达式会导致C解析器出现问题。)