1.類的本質(zhì)
類的本質(zhì)其實(shí)也是一個(gè)對(duì)象(類對(duì)象)
程序中第一次使用該類的時(shí)候被創(chuàng)建,在整個(gè)程序中只有一份。
此后每次使用都是這個(gè)類對(duì)象,它在程序運(yùn)行時(shí)一直存在。
類對(duì)象是一種數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)類的基本信息:類大小,類名稱,類的版本,繼承層次,以及消息與函數(shù)的映射表等
類對(duì)象代表類,Class類型,對(duì)象方法屬于類對(duì)象
如果消息的接收者是類名,則類名代表類對(duì)象
所有類的實(shí)例都由類對(duì)象生成,類對(duì)象會(huì)把實(shí)例的isa的值修改成自己的地址,每個(gè)實(shí)例的isa都指向該實(shí)例的類對(duì)象
2.如何獲取類對(duì)象
2.1.通過實(shí)例對(duì)象
格式:[實(shí)例對(duì)象 ? class ];
如: ? [person class];
2.2.通過類名獲取(類名其實(shí)就是類對(duì)象)
格式:[類名 class];
如:[GSPerson class]
3.類對(duì)象的用法
3.1.用來調(diào)用類方法
? ?[GSPerson test];
? ?Class c = [GSPerson class];
? ?[c test];
3.2.用來創(chuàng)建實(shí)例對(duì)象
? ?GSPerson *p = [GSPerson new];
? ?Class c = [GSPerson class];
? ?GSPerson *p1 = [c new];
4.類對(duì)象的存儲(chǔ)
5.OC實(shí)例對(duì)象 類對(duì)象 元對(duì)象之間關(guān)系
? ?5.1Objective-C是一門面向?qū)ο蟮木幊陶Z(yǔ)言。
? ?每一個(gè)對(duì)象 都是一個(gè)類的實(shí)例。
? ?每一個(gè)對(duì)象 都有一個(gè)名為isa的指針,指向該對(duì)象的類。
? ?每一個(gè)類??述了一系列它的實(shí)例的特點(diǎn),包括成員變量的列表,成員函數(shù)的列表等。
? ?每一個(gè)對(duì)象都可以接受消息,而對(duì)象能夠接收的消息列表是保存在它所對(duì)應(yīng)的類中。
? ?5.2.在Xcode中輸入NSObject按住command進(jìn)入NSObject頭文件,通過頭文件我們可以看到,NSObject就是一個(gè)包含isa指針的結(jié)構(gòu)體,如下圖所示:
? 5.3.按照面向?qū)ο笳Z(yǔ)言的設(shè)計(jì)原則,所有事物都應(yīng)該是對(duì)象(嚴(yán)格來說 Objective-C并沒有完全做到這一點(diǎn),因?yàn)樗衖nt,double這樣的簡(jiǎn)單變量類型)
? ? 在Objective-C語(yǔ)言中,每一個(gè)類實(shí)際上也是一個(gè)對(duì)象。每一個(gè)類也有一個(gè)名為isa的指針。每一個(gè)類都可以接受消息,例如[NSObject new],就是向NSObject這個(gè)類發(fā)送名為new的消息。
? ??在Xcode中輸入Class,按住command進(jìn)入Class頭文件,通過頭文件我們可以看到,Class也是一個(gè)包含isa指針的結(jié)構(gòu)體,如下圖所示。
? ?5.4.因?yàn)轭愐彩且粋€(gè)對(duì)象,那它也必須是另一個(gè)類的實(shí)例,這個(gè)類就是元類 (metaclass)。
? ?元類保存了類方法的列表。當(dāng)一個(gè)類方法被調(diào)用時(shí),元類會(huì)首先查找它本身是否有該類方法的實(shí)現(xiàn),如果沒有則該元類會(huì)向它的父類查找該方法,直到一直找到繼承鏈的頭。
? ?元類(metaclass)也是一個(gè)對(duì)象,那么元類的isa指針又指向哪里呢?為了設(shè)計(jì)上的完整,所有的元類的isa指針都會(huì)指向一個(gè)根元類(root metaclass)。
? ?根元類(root metaclass)本身的isa指針指向自己,這樣就行成了一個(gè)閉環(huán)。上面說??到,一個(gè)對(duì)象能夠接收的消息列表是保存在它所對(duì)應(yīng)的類中的。在實(shí)際編程中,我們幾乎不會(huì)遇到向元類發(fā)消息的情況,那它的isa 指針在實(shí)際上很少用到。不過這么設(shè)計(jì)保證了面向?qū)ο蟮母蓛?即所有事物都是對(duì)象,都有isa指針。
? ?由于類方法的定義是保存在元類(metaclass)中,而方法調(diào)用的規(guī)則是,如果該類沒有一個(gè)方法的實(shí)現(xiàn),則向它的父類繼續(xù)查找。所以為了保證父類的類方法可以在子類中可以被調(diào)用,所以子類的元類會(huì)繼承父類的元類,換而言之,類對(duì)象和元類對(duì)象有著同樣的繼承關(guān)系。
?
?5.5.下面這張圖或許能夠 讓大家對(duì)isa和繼承的關(guān)系清楚一些
上圖中,最讓人困惑的莫過于Root Class了。在實(shí)現(xiàn)中,Root Class是指NSObject,我們可以從圖中看出:
NSObject類對(duì)象包括它的對(duì)象實(shí)例方法。
NSObject的元對(duì)象包括它的類方法,例如new方法。
NSObject的元對(duì)象繼承自NSObject類。
一個(gè)NSObject的類中的方法同時(shí)也會(huì)被NSObject的子類在查找方法時(shí)找到。
6.詳細(xì)講解:(GSPerson類)
1.程序啟動(dòng)后,系統(tǒng)會(huì)將所有類加載進(jìn)內(nèi)存-即代碼區(qū)。
2.當(dāng)需要用到GSPerson類時(shí),系統(tǒng)會(huì)先在堆中創(chuàng)建一個(gè)對(duì)象,俗稱類對(duì)象。
? ? 2.1.內(nèi)部創(chuàng)建一個(gè)isa指針指向源類對(duì)象
? ? 2.2系統(tǒng)會(huì)在類對(duì)象中包含該類的所有成員屬性、對(duì)象方法
? ? 2.3源類對(duì)象:
? ? ? ? 2.3.1內(nèi)部創(chuàng)建一個(gè)isa指針指向根源類對(duì)象-NSObject
? ? ? ? 2.3.2系統(tǒng)會(huì)在類對(duì)象中包含該類對(duì)象方法
? ? ? ? ?2.3.3根源類對(duì)象-NSObject
? ? ? ? ? ? ?2.3.3.1內(nèi)部創(chuàng)建一個(gè)isa指針指向自己本身
3.[[GSPerson alloc] init]系統(tǒng)做了三件事:
? ? 3.1.alloc:
? ? ? ? 3.1.1.內(nèi)部創(chuàng)建一個(gè)isa指針指向類對(duì)象
? ? ? ? 3.1.2.在堆中分配一塊存儲(chǔ)空間
? ? ? ? 3.1.3.初步初始化,將成員變量初始化為零
? ? ? ? 3.1.4.返回對(duì)象
? ? 3.2.init:對(duì)成員變量進(jìn)行初始化
? ? 3.3.返回對(duì)象
注:蘋果對(duì)+(instance)alloc:方法說明
注:附上整個(gè)過程圖一張