iOS小记iOS开发 oc中重要知识点架构师之路

类的本质-类对象

2016-11-06  本文已影响609人  VV木公子

前言

今天整理了下自己电脑里的一些碎片笔记,时间有限只整理了这篇文章——类的本质,大家可以进行参考。

1.本质

2.如何获取类对象

格式:[实例对象 class];
如:   [dog class];
格式:[类名 class];
如:[Dog class]

3.类对象的用法

[Dog test];

Class c = [Dog class];
[c test];
Dog *g = [Dog new];

Class c = [Dog class];
Dog *g1 = [c new];

4.类对象的存储

存储.png

5.OC实例对象、类对象、元数据、之间关系

NSObject.h
@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}
objc.h
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};
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;

其中:实线箭头代表类的继承关系,比如EOCStudent继承自EOCPerson,也就是说,EOCStudent是EOCPerson的子类。就可以用实线表示这种继承关系:EOCStudent —>EOCPerson。

虚线箭头代表对象和类的从属关系,比如一个对象student属于EOCStudent类,也就是说,student是EOCStudent的实例。就可以用虚线表示这种从属关系:student—>EOCStudent。

引用《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》中的一段话:superclass指针确定了继承关系,而isa指针描述了实例所属的类。通过这张布局关系图即可进行“类型信息查询”。我们能查出对象是否能够响应某个选择子(selector),是否遵从某项协议,并且能够看出某对象位于集成体系的哪一部分

继承/从属关系图

当对象收到消息时,消息函数首先根据该对象的isa
指针找到该对象所对应的类的方法表,并从表中寻找该消息对应的方法selector。如果找不到,objc_msgSend
将继续从父类中寻找,直到NSObject
类。一旦找到了方法选标, objc_msgSend
则以消息接收者对象为参数调用,调用该选标对应的方法实现。调用方式:objc_msgSend(receiver, selector, arg1, arg2, ...)
这就是在运行时系统中选择方法实现的方式。在面向对象编程中,一般称作方法和消息动态绑定的过程。
为了加快消息的处理过程,运行时系统通常会将使用过的方法选标和方法实现的地址放入缓存中。每个类都有一个独立的缓存,同时包括继承的方法和在该类中定义的方法。消息函数会首先检查消息接收者对象对应的类的缓存(理论上,如果一个方法被使用过一次,那么它很可能被再次使用)。如果在缓存中已经有了需要的方法选标,则消息仅仅比函数调用慢一点点。如果程序运行了足够长的时间,几乎每个消息都能在缓存中找到方法实现。程序运行时,缓存也将随着新的消息的增加而增加。

6.如何查询类型信息

可以使用“类型信息查询方法”来查询类的继承体系。其中,“isMemberOfClass:”可以判断对象是否是特定类的实例。而”isKindOfClass:”可以判断对象是否是某个类或者其派生子类的实例。而本质上,这两个类型信息查询方法是使用对象的isa指针获取对象所属的类(因为类对象也是对象,所以也有isa指针,该指针指向元类,也就是类对象所属的类),然后通过类继承体系中的superclass指针在继承体系中游走。Objective-C与其他语言不同,Objective-C必须查询类型信息,才能完全了解对象的真实类型。

另外,需要注意的是,我们从集合对象(collection)中获取的对象,通常会用到这两个查询类型信息的方法。因为从集合对象中取出来的对象不是强类型的(strongly typed),其类型通常是id。回想一下,我们从一个数组中取出来的对象,其返回值是id类型的。这就是为什么我们可以在这个取出来的对象身上通过中括号”[ ]”的形式调用任何方法,却不能通过点语法来调用方法。不过,为了安全起见,如果涉及到对集合对象中的某个对象进行操作,我们还是需要做一下类型判断比较好。如下所示:

    for (id object in array) {
        if (object isKindOfClass:[NSString class]) {
            // object is an instance of NSString
        }
    }

当然,也可以用比较类对象是否等同的方法来判断对象是否属于某个类。若是如此,那就应该使用==操作符,而不要使用比较Objective-C对象使常用的“isEqual:”方法。因为==操作符比较的是指针是否相等,也就是比较内存地址是否相同。而"isEqual:"比较的是两个Objective-C对象的值是否相等。此处用==操作符,原因在于,类对象类对象是“单例”,在应用程序范围内,每个类的Class仅有一个实例,在整个内存中仅有一份(因为+(void)load方法和+ (void)initialize只被调用一次)。所以也可以用下面这种方进行比较:

if ([object class] == [EOCSomeClass class]) {
        // object is an instance of EOCSomeClass
}

虽然调用class方法和isKindOfClass:方法都可以查询一个对象的类型。但是还是建议使用后者。下面笔者引用《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》中的一段话来进行解释:

虽然使用"class方法"也可以查询对象的类型信息。但是还是建议使用isKindOfClass:这样的类型信息查询方法。因为后者可以正确处理那些使用了消息传递机制对象。比方说某个对象可能会把其的所有选择子(selector)都转发给另一个对象(开启了消息转发功能)。这样的对象叫做”代理(proxy)“,此种对象所属的类均以NSProxy为根类(root class)。通常情况下,如果在此种代理对象上调用class方法,那么返回的是代理对象本身(NSProxy的子类),而非接受代理的对象所属的类。然而,若是改用“isKindOfClass:”这样的类型信息查询方法,那么代理对象就会把这条消息转给“接受代理的对象(proxy object)”。也就是说,这条消息(指isKindOfClass:)的返回值与直接接受代理的对象身上查询其类型信息所得的结果相同。因此,这样查出来的类对象与直接通过class方法所返回的那个类对象不同,class方法所返回类表示发起代理的对象,而非接受代理的对象

文/VV木公子(简书作者)
PS:如非特别说明,所有文章均为原创作品,著作权归作者所有,转载请联系作者获得授权,并注明出处,所有打赏均归本人所有!

如果您是iOS开发者,或者对本篇文章感兴趣,请关注本人,后续会更新更多相关文章!敬请期待!

上一篇下一篇

猜你喜欢

热点阅读