1.類的本質
- 類的本質其實也是一個對象(類對象)
- 程序中第一次使用該類的時候被創(chuàng)建,在整個程序中只有一份洪灯。
- 此后每次使用都是這個類對象捐康,它在程序運行時一直存在。
- 類對象是一種數據結構,存儲類的基本信息:類大小,類名稱,類的版本坎吻,繼承層次,以及消息與函數的映射表等
- 類對象代表類,Class類型,對象方法屬于類對象
- 如果消息的接收者是類名,則類名代表類對象
- 所有類的實例都由類對象生成,類對象會把實例的isa的值修改成自己的地址,每個實例的isa都指向該實例的類對象
2.如何獲取類對象
- 通過實例對象
格式:[實例對象 class ];
如: [dog class];
- 通過類名獲取(類名其實就是類對象)
格式:[類名 class];
如:[Dog class]
3.類對象的用法
- 用來調用類方法
[Dog test];
Class c = [Dog class];
[c test];
- 用來創(chuàng)建實例對象
Dog *g = [Dog new];
Class c = [Dog class];
Dog *g1 = [c new];
4.類對象的存儲
類對象的存儲.png
5.OC實例對象 類對象 元對象之間關系
-
Objective-C是一門面向對象的編程語言宇葱。
- 每一個對象 都是一個類的實例瘦真。
- 每一個對象 都有一個名為isa的指針,指向該對象的類。
- 每一個類??述了一系列它的實例的特點,包括成員變量的列表,成員函數的列表等黍瞧。
- 每一個對象都可以接受消息,而對象能夠接收的消息列表是保存在它所對應的類中诸尽。
在Xcode中按Shift + Command + O打開文件搜索框,然后輸入NSObject.h和objc.h,可以打開 NSObject的定義頭文件,通過頭文件我們可以看到,NSObject就是一個包含isa指針的結構體,如下圖所示:
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;
};
- 按照面向對象語言的設計原則,所有事物都應該是對象(嚴格來說 Objective-C并沒有完全做到這一點,因為它有int,double這樣的簡單變量類型)
- 在Objective-C語言中,每一個類實際上也是一個對象雷逆。每一個類也有一個名為isa的指針弦讽。每一個類都可以接受消息,例如[NSObject new],就是向NSObject這個類發(fā)送名為new的消息。
- 在Xcode中按Shift + Command + O,然后輸入runtime.h,可以打開Class的定義頭文件,通過頭文件我們可以看到,Class也是一個包含isa指針的結構體,如下圖所示膀哲。(圖中除了isa外還有其它成員變量,但那是為了兼容非2.0版的Objective-C的遺留邏輯,大家可以忽略它往产。)
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)。
- 元類保存了類方法的列表某宪。當一個類方法被調用時,元類會首先查找它本身是否有該類方法的實現,如果沒有則該元類會向它的父類查找該方法,直到一直找到繼承鏈的頭仿村。
- 元類(metaclass)也是一個對象,那么元類的isa指針又指向哪里呢?為了設計上的完整,所有的元類的isa指針都會指向一個根元類(root metaclass)。
- 根元類(root metaclass)本身的isa指針指向自己,這樣就行成了一個閉環(huán)兴喂。上面說??到,一個對象能夠接收的消息列表是保存在它所對應的類中的蔼囊。在實際編程中,我們幾乎不會遇到向元類發(fā)消息的情況,那它的isa 指針在實際上很少用到。不過這么設計保證了面向對象的干凈,即所有事物都是對象,都有isa指針衣迷。
- 由于類方法的定義是保存在元類(metaclass)中,而方法調用的規(guī)則是,如果該類沒有一個方法的實現,則向它的父類繼續(xù)查找畏鼓。所以為了保證父類的類方法可以在子類中可以被調用,所以子類的元類會繼承父類的元類,換而言之,類對象和元類對象有著同樣的繼承關系。
下面這張圖或許能夠 讓大家對isa和繼承的關系清楚一些
isa和繼承的關系.png
類的本質isa和繼承的關系.png
- 上圖中,最讓人困惑的莫過于Root Class了壶谒。在實現中,Root Class是指 NSObject,我們可以從圖中看出:
- NSObject類對象包括它的對象實例方法云矫。
- NSObject的元對象包括它的類方法,例如new方法。
- NSObject的元對象繼承自NSObject類汗菜。
- 一個NSObject的類中的方法同時也會被NSObject的子類在查找方法時找到让禀。