美文网首页编写高质量代码的52个有效方法
52个有效方法(14) - 理解“类对象”的用意

52个有效方法(14) - 理解“类对象”的用意

作者: SkyMing一C | 来源:发表于2018-09-03 16:34 被阅读5次

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

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

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

    相关文章

      网友评论

        本文标题:52个有效方法(14) - 理解“类对象”的用意

        本文链接:https://www.haomeiwen.com/subject/qhhlbftx.html