52个有效方法(14) - 理解“类对象”的用意
2018-09-03 本文已影响5人
SkyMing一C
在OC中,类,对象和方法其实都是一个C的结构体。
描述Objective-C对象所用的数据结构定义
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;//=> 指向对象所属的类
};
每个对象结构体的首个成员是Class类的变量。该变量定义了对象所属的类,通常称为“is a”指针。
描述Class对象所用的数据结构定义
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
//这里struct类型是c++对c的扩展,除了访问权限是public之外其他的和class一模一样
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
- 此结构体的首个变量也是
isa
指针,这说明Class
本身亦为Objective-C对象。 - 结构体里还有个变量叫做
super_class
,它定义了本类的超类。 - 类对象所属的类型(也就是isa指针所指向的类型)是另外一个类,叫做“元类”(metaclass),用来表述类对象本身所具备的元数据。“类方法”就定义于此处,因为这些方法可以理解成类对象的实例方法。
- 每个类仅有一个“类对象”,而每个“类对象”仅有一个与之相关的“元类”。
元类与元类之间存在跟类一致的继承关系
类继承体系1 类继承体系2类的继承关系的相关判断
- 判断一个对象是否属于一个特定的类
NSMutableDictionary *mDic = [NSMutableDictionary new];
[mDic isMemberOfClass:[NSDictionary class]]; //NO
[mDic isMemberOfClass:[NSMutableDictionary class]]; //YES
[mDic class] == [NSMutableDictionary class] //YES
最后==这种判断是因为每个类的class是单例模式,仅有一个这样的对象。但是并不推荐这样做,因为在对象的类实现了转发机制,并且把所有的转发都发给代理对象的时候,就判断不准确了。比如如下这种情况:
@interface MyProxy : NSProxy
@property (nonatomic,strong) id obj;
@end
@implementation MyProxy
- (Class)class{
return [self.obj class];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
return [self.obj methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation{
[invocation invokeWithTarget:self.obj];
}
@end
//执行代码
id proxy = [MyProxy alloc];
((MyProxy *)proxy).obj = [[NSString alloc] init];
[proxy class] == [MyProxy class]; //NO
- 判断一个对象是否是一个类或者其子类
[mDic isKindOfClass:[NSMutableDictionary class]]; //YES
[mDic isKindOfClass:[NSDictionary class]]; //YES
[mDic isKindOfClass:[NSArray class]]; //NO
要点
-
每个实例都有一个指向Class对象的指针,用以表明其类型,而这些Class对象则构成了类的继承体系。
-
如果对象类型无法在编译期确定,那么就应该使用类型信息查询方法来探知。
-
尽量使用类型信息查询方法来确定对象类型,而不要直接比较类对象,因为某些对象可能实现了消息转发功能。