编写高质量代码的52个有效方法

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;
元类与元类之间存在跟类一致的继承关系
类继承体系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
要点
  1. 每个实例都有一个指向Class对象的指针,用以表明其类型,而这些Class对象则构成了类的继承体系。

  2. 如果对象类型无法在编译期确定,那么就应该使用类型信息查询方法来探知。

  3. 尽量使用类型信息查询方法来确定对象类型,而不要直接比较类对象,因为某些对象可能实现了消息转发功能。

上一篇下一篇

猜你喜欢

热点阅读