今天整理了下本身电脑里的一些碎片笔记,时间有限只整理了这篇文章——类的本质,你们能够进行参考。编程
经过实例对象数组
格式:[实例对象 class]; 如: [dog class];
经过类名获取(类名其实就是类对象)安全
格式:[类名 class]; 如:[Dog class]
[Dog test]; Class c = [Dog class]; [c test];
Dog *g = [Dog new]; Class c = [Dog class]; Dog *g1 = [c new];
Objective-C是一门面向对象的编程语言。ruby
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;
由于类也是一个对象,那它也必须是另外一个类的实例,这个类就是元类 (metaclass)。数据结构
其中
:实线箭头表明类的继承关系,好比EOCStudent继承自EOCPerson,也就是说,EOCStudent是EOCPerson的子类。就能够用实线表示这种继承关系:EOCStudent —>EOCPerson。编程语言
虚线箭头表明对象和类的从属关系,好比一个对象student属于EOCStudent类,也就是说,student是EOCStudent的实例。就能够用虚线表示这种从属关系:student—>EOCStudent。函数
引用《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》中的一段话:superclass指针肯定了继承关系,而isa指针描述了实例所属的类。经过这张布局关系图便可进行“类型信息查询”。咱们能查出对象是否可以响应某个选择子(selector),是否听从某项协议,而且可以看出某对象位于集成体系的哪一部分。布局
可使用“类型信息查询方法”来查询类的继承体系。其中,“isMemberOfClass:”能够判断对象是不是特定类的实例。而”isKindOfClass:”能够判断对象是不是某个类或者其派生子类的实例。而本质上,这两个类型信息查询方法是使用对象的isa指针获取对象所属的类(由于类对象也是对象,因此也有isa指针,该指针指向元类,也就是类对象所属的类),而后经过类继承体系中的superclass指针在继承体系中游走。Objective-C与其余语言不一样,Objective-C必须查询类型信息,才能彻底了解对象的真实类型。ui
另外,须要注意的是,咱们从集合对象(collection)中获取的对象,一般会用到这两个查询类型信息的方法。由于从集合对象中取出来的对象不是强类型的(strongly typed),其类型一般是id。回想一下,咱们从一个数组中取出来的对象,其返回值是id类型的。这就是为何咱们能够在这个取出来的对象身上经过中括号”[ ]”的形式调用任何方法,却不能经过点语法来调用方法。不过,为了安全起见,若是涉及到对集合对象中的某个对象进行操做,咱们仍是须要作一下类型判断比较好。以下所示:spa
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开发者,或者对本篇文章感兴趣,请关注本人,后续会更新更多相关文章!敬请期待!