今天整理了下本身電腦裏的一些碎片筆記,時間有限只整理了這篇文章——類的本質,你們能夠進行參考。編程
經過實例對象數組
格式:[實例對象 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開發者,或者對本篇文章感興趣,請關注本人,後續會更新更多相關文章!敬請期待!