我的理解是,对象和类在Objective-C的只是结构.
他们分别只是:
struct objc_class *
和:
struct objc_object *
问题#1:
objc_msgSend(id self, SEL _cmd);
id
据我所知是类型 struct objc_object *
但是当我们调用类方法时,类是一个类struct objc_class *
,
我希望它会引起问题或者喊出某种警告,例如"嘿,这里的错误类型,我的朋友".
但事实并非如此.
为什么?
这只是为了满足我的好奇心,因为即使没有完全理解这一点,它似乎也没有给我带来任何麻烦(到目前为止).但我想深入挖掘并学习基本原理/"特点".
问题2:
由于根据我的经验没有警告(与问题#1有关),因此我不太确定它们可以互换使用.
能struct objc_class *
和struct objc_object *
真正使用互换?
如是:
你能告诉我一个场景和样本何时/如何/为什么我们需要互换使用这些?
什么是好处(如果有的话),缺点(如果有的话)和" 陷阱 "(需要注意的事项;如果有的话)这样做?
Rob Napier.. 8
My understanding is that objects and classes in Objective-C are just structs.
This isn't really true, particularly since ObjC2, and definitely isn't a good way of thinking about it. The "struct" in question has a single field (isa
) defined. That's it. It's a "struct" in name only.
Note that under ARC objects and structs are treated differently by the compiler. Objects pointers will get special handling (including nil-initialization) that a struct pointer will not. The compiler will also apply ->
differently to an object than it does to a struct. A struct pointer must have a field with the name given after the ->
. objc_object
only has one field (isa
). Since class hierarchies can be defined and redefined at runtime, the compiler cannot evaluate ->
for an object at compile time as it does for a struct.
I make this point because in C++, objects and structs are just slightly different versions of the same thing, and you can easily swap between them. You cannot safely do that in ObjC. They're not nearly as similar.
But when we call a class method, a class, which is of type
struct objc_class *
, I would expect it to cause problem…
This is because classes are objects. Objects are not defined in terms of being of type objc_object
. They're defined in terms of having an isa
field (it used to be a pointer, but now it might be a pointer, or it might not). This is part of the problem of assuming that the typedef is the important thing. It isn't. What matters is whether it acts like an object. Objective-C is a mostly duck-typed language. If it acts like an object, it's an object.
BTW, NSProxy
also lives in this weird almost-an-object world. If you note its definition, it does not inherit from anything, but it does declare an isa
field as its first ivar. That's the critical part of making it act like an object.
Can struct objc_class * and struct objc_object * really be used interchangeably?
No. You can generally pass a class to anything that wants an object (since a class is an object), but you cannot pass an object to things that want a class.
KudoCC.. 5
我在runtime.h文件中找到它.
struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #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; struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };
objc_class和objc_object都有isa变量,objc_object中的isa指向描述实例并存储实例方法列表的Class.objc_class中的Isa也指向Class,但它是描述类并存储类方法列表的元类.
该链接对您有用.
我已经模拟了病情.
struct A { int a ; } ; typedef struct A *PA ; struct B { int a ; int b ; } ; void dosomething(PA pa) { printf("%d", (*pa).a) ; } + (void)hei { struct B b ; b.a = 10 ; b.b = 20 ; // without forced cast, i will get a warning but work well dosomething((PA)&b) ; }
您可以使用struct B *
而不是struct A *
因为编译器和链接器int a
位于相同的相对地址中.
为什么编译器在我们调用传递struct objc_class *
给它的类方法时不会抱怨objc_msgSend(id self, SEL _cmd);
,在我看来编译器会考虑它.
我在runtime.h文件中找到它.
struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #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; struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };
objc_class和objc_object都有isa变量,objc_object中的isa指向描述实例并存储实例方法列表的Class.objc_class中的Isa也指向Class,但它是描述类并存储类方法列表的元类.
该链接对您有用.
我已经模拟了病情.
struct A { int a ; } ; typedef struct A *PA ; struct B { int a ; int b ; } ; void dosomething(PA pa) { printf("%d", (*pa).a) ; } + (void)hei { struct B b ; b.a = 10 ; b.b = 20 ; // without forced cast, i will get a warning but work well dosomething((PA)&b) ; }
您可以使用struct B *
而不是struct A *
因为编译器和链接器int a
位于相同的相对地址中.
为什么编译器在我们调用传递struct objc_class *
给它的类方法时不会抱怨objc_msgSend(id self, SEL _cmd);
,在我看来编译器会考虑它.
My understanding is that objects and classes in Objective-C are just structs.
This isn't really true, particularly since ObjC2, and definitely isn't a good way of thinking about it. The "struct" in question has a single field (isa
) defined. That's it. It's a "struct" in name only.
Note that under ARC objects and structs are treated differently by the compiler. Objects pointers will get special handling (including nil-initialization) that a struct pointer will not. The compiler will also apply ->
differently to an object than it does to a struct. A struct pointer must have a field with the name given after the ->
. objc_object
only has one field (isa
). Since class hierarchies can be defined and redefined at runtime, the compiler cannot evaluate ->
for an object at compile time as it does for a struct.
I make this point because in C++, objects and structs are just slightly different versions of the same thing, and you can easily swap between them. You cannot safely do that in ObjC. They're not nearly as similar.
But when we call a class method, a class, which is of type
struct objc_class *
, I would expect it to cause problem…
This is because classes are objects. Objects are not defined in terms of being of type objc_object
. They're defined in terms of having an isa
field (it used to be a pointer, but now it might be a pointer, or it might not). This is part of the problem of assuming that the typedef is the important thing. It isn't. What matters is whether it acts like an object. Objective-C is a mostly duck-typed language. If it acts like an object, it's an object.
BTW, NSProxy
also lives in this weird almost-an-object world. If you note its definition, it does not inherit from anything, but it does declare an isa
field as its first ivar. That's the critical part of making it act like an object.
Can struct objc_class * and struct objc_object * really be used interchangeably?
No. You can generally pass a class to anything that wants an object (since a class is an object), but you cannot pass an object to things that want a class.