1. objC 动态类型(dynamic typing)

来源:互联网 发布:什么是事件驱动编程 编辑:程序博客网 时间:2024/05/16 00:40

objC动态类型(dynamic typing)

       动态类型概念

       在objC的语法中,所有的类实例都是动态类型的,即在编译过程中,不强制检查当前的类型的数据和方法是否合法;检查的合法性放到了运行时检查。这样增大了运行时的风险,但同时增加了程序的灵活性。

       在NeXT Objective-C中,要对当前对象是否能够调用当前消息,以及消息所携带的参数类型进行类型检查,不合格时,给出警告。此特性的应用场合有,可以把任意的类型的对象放到一个容器中。既弥补了没有模板的短板,而且比模板还要灵活,C++模板需要所有的元素类型相同,但objC中不需要。

       动态类型原理

       首先,在objC中一个重要的类,为类结构类型,是实现动态类型识别的核心人物。也就是说,如果想要有动态识别的特性,必须要objc_class来配合。具体的定义如下所示:

    struct objc_class {        struct objc_class *meta_class_isa; //指向元类信息的指针,元类包含静态变量和静态方法等信息        struct objc_class *super_class; //指向父类的指针        const char *name;        long version;        long info;//标识位,具体有如下的掩码:CLS_CLASS:代表当前结构是类对象属性;CLS_META:当前结构为原类信息;其他省略...        long instance_size;//当前实例的大小        struct objc_ivar_list *ivars;// 实例成员变量的说明        struct objc_method_list **methodLists;//函数的列表:如果info==CLS_CLASS表示对象方法;info==CLS_META表示类方法        struct objc_cache *cache;//实例在调用类方法时,把方法放到此缓存中,以加快调用速度        struct objc_protocol_list *protocols;    };

       存在继承关系的类,像家谱一样,都会形成一张关系网。我们暂且称其为“类别型录”(按照侯俊杰先生对MFC中的RTTI对存在继承关系类的关系网)。有了这个“类别型录”,就可以实现动态的类型识别(dynamic type)以及动态的方法调用(dynamic binding)。此网络可以用图1来表示:


                                                          图1 objC中的类别型录

在OpenStep中,所有类都要从根类进行继承。最常见根类NSObject,NSProxy,

    @interface NSProxy <NSObject> {        Class isa;    }    @interface NSObject <NSObject> {        Class isa;    }

        这些根类都含有一个指向object_class类型的指针isa。显然,相同类所有实例的isa指针都应该指向相同的地址,因为,相同类的属性和方法都应当是相同的。通过调试,验证isa的地址确实是相同的。如下图2



                                                               图 2 相同类的实例中的isa是指向相同地址

       当创建一个实例对象时,实例对象的isa指向当前类在家谱中位置的地址。要判断实例类型时,就直接去家谱中去查询。例如,要对一个实例对象发送某个消息时,就到isa指向的类对象中的methodLists中去查找当前的链表中是否有相同名字的SEL,如果没有,就向super_class中继续,直到NSObject为止。

      可以看出,objC的函数的调用时候,全部都为动态调用,也就是说,普通函数调用和多态调用所采用的方式是相同的。这一点和C++是不同的。在C++中,普通函数的调用是静态调用,只有多态函数调用是动态调用。

      动态类型的应用

      在Next Step中,所有的类必须要遵循protocol NSObject协议,此协议定义为

/***************Basic protocols***************/@protocol NSObject- (BOOL)isEqual:(id)object;- (NSUInteger)hash;- (Class)superclass;- (Class)class;- (id)self;- (NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;- (id)performSelector:(SEL)aSelector;- (id)performSelector:(SEL)aSelector withObject:(id)object;- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;- (BOOL)isProxy;- (BOOL)isKindOfClass:(Class)aClass;- (BOOL)isMemberOfClass:(Class)aClass;- (BOOL)conformsToProtocol:(Protocol *)aProtocol;- (BOOL)respondsToSelector:(SEL)aSelector;- (id)retain NS_AUTOMATED_REFCOUNT_UNAVAILABLE;- (oneway void)release NS_AUTOMATED_REFCOUNT_UNAVAILABLE;- (id)autorelease NS_AUTOMATED_REFCOUNT_UNAVAILABLE;- (NSUInteger)retainCount NS_AUTOMATED_REFCOUNT_UNAVAILABLE;- (NSString *)description;@optional- (NSString *)debugDescription;@end

这些函数中,有很多是和动态类型和动态绑定有关系的接口函数。如

[object isKindOfClass: some_class] : 表示当前object是否是some_class类型的实例或者继承于some_class类型的实例;

[object isMemberOfClass: some_class]: 表示当前的object是否是some_class类型的实例;

[object respondsToSelector: SELFunction]: 表示判断当前的实例是否有SELFunction的SEL调用;

[object performSelector: SELFunction] : 表示要执行SEL指定的函数;






原创粉丝点击