oc物件模型理解

2021-07-03 15:16:55 字數 3392 閱讀 9986

首先,oc是一門程式語言,foundation是乙個為oc而生的為了方便程式設計師使用的程式設計框架。

這裡可以用各司其職來形容它們:

作為一門物件導向程式設計語言,oc本身只需要關注自己的物件模型的管理,也就是它只需要管理好oc物件,類,這些東西的組織和聯絡。

而作為乙個基於oc的框架,foundation關注的則是讓程式設計師更方便的使用oc語言進行程式設計。

以上的說明看似是廢話,或者說只要是使用oc的程式設計師都知道的。但是我覺得我沒有深刻的理解它,我本身是大三學生,學習的過程中就喜歡深究原理,加上之前鼓搗過半年一年的嵌入式,什麼東西都感覺還是弄得清清楚楚,用起來才會踏實,所以翻閱各種帖子研究了一下oc物件模型的實現,在這裡總結一下。

從很眼熟的nsstring和nsobject開始吧。

nsstring不用說了,字串類,每天都在用。nsobject這個也熟的不行,我們使用的類基本上都繼承自它。然而這裡要說的是,嚴格來說,它們的等級不同,或者說分屬不同的範圍:nsobject屬於oc語言定義的內容,而nsstring則是由foundation框架提供的。

乙個很明顯的地方可以看出,nsobject類和我們使用的繼承自它的各種類的分別。在xcode按command + shift + o,分別搜尋nsobject.h檔案和nsstring.h檔案可以看到,後者存在於foundation框架包中,而nsobject.h則user/include下面。

看一下nsobject的定義可以看到,它本身提供的屬性和方法,基本上都是關於物件的分配,初始化,拷貝,記憶體管理,方法的呼叫,父類子類的關係等等。

這些就是上面說的,乙個程式語言需要操心的點,作為一門物件導向的程式語言,它總要告訴程式設計者,如何初始化乙個物件,如何分配記憶體,如何拷貝物件等等。oc自己定義了乙個根類nsobject,並為根類提供了物件的記憶體分配,初始化,物件管理,物件模型的實現,使用時只需要繼承nsobject類,就可以實現類的定義,物件的初始化,拷貝,銷毀,方法呼叫等功能,這就是oc提供的東西。

但是oc並不提供字串的定義,image的定義,文字框的定義,陣列和字典等等,這些都是由基於oc的框架提供的,也就是說,oc提供給我們建立,使用,管理類和物件的功能,而字串,陣列這些東西,需要我們使用oc提供的功能來自己實現,foundation的作用就在此,我們不用再自己寫乙個繼承自nsobject的「string」類,再寫一大堆方法來使用字串,foundation已經寫好了nsstring供我們使用,uikit等其它框架均是如此。

所以說嚴格來說,nsobject是oc這門語言提供的類,我們可以繼承它來建立自己的類,建立物件,它是乙個工具,也是oc這門語言的核心。而對於foundation可以這麼理解:由於程式設計經常要使用字串,陣列,字典等型別的資料,而oc語言在一開始僅僅提供了nobject這乙個根類,每個要使用它的人都需要自己編寫繼承自它的字串類和陣列類,這非常麻煩並且不合理,所以就有一群人做了這個工作,寫好了一大堆常用的型別,每個oc的程式設計師都使用它來程式設計,這樣就很方便且利於傳播了,它就是foundation。

講到這裡,就清楚了oc和foundation的聯絡,那下面看一下oc的物件模型的實現。

對於一門物件導向的程式語言,類,物件,方法(也叫函式,oc中叫訊息)是核心,oc是怎麼組織物件,類,和方法的呢?

上面說過,每乙個類都繼承自nsobject類,也就是說,nsobject類如果有成員變數,那麼其它的類就都有這個變數,當然是有的,這個成員變數是isa:

isa的型別是class,就是說,每乙個物件:nsstring,nsarray,uilabel等等這些類例項出的變數,裡面都包含乙個class型別的isa變數,class是什麼類呢:

它是乙個指標,也就是說isa是乙個指向objc_class結構體的指標,即每乙個物件中都包含乙個objc_class結構體,這個結構體的定義是怎樣的呢?

看到這裡可能有點疑惑了,isa本來就是乙個指向objc_class的指標,而objc_class結構體中又包含isa指標?很好理解,由於每個物件內部都包含objc_class結構體,所以,這個結構體中的isa指標使用來指向別的物件的,即每個物件都包含乙個isa指標,可以用這個指標指向別的物件來建立聯絡。

我們知道,使用乙個物件的時候,無非就是兩點,物件中的例項變數和方法,我們在定義乙個類的時候,會定義自己的例項變數和方法,而方法又分為兩種,動態方法和靜態方法,動態方法是物件方法,靜態方法是類方法,那他們分別是怎麼聯絡的呢?

首先要明確的是,類也是乙個物件,對於oc來說一切都是物件,類也有isa指標。

我們定義了乙個新的類,給它新增了一些新的成員變數和類方法,物件方法,然後用這個類例項出了乙個物件,我們呼叫這個物件的物件方法,也可以呼叫這個類的類方法,然而這個物件在記憶體中的儲存,卻只儲存了成員變數,並沒有儲存方法,那物件是怎麼執行方法的呢:

乙個物件在記憶體中的儲存可以看成乙個結構體,首先,這個結構體中有自己的成員變數,然後還有父類的成員變數,父類的父類的成員變數,這樣按照繼承鏈找上去,最終會找到nsobject類,上面說過,nsobject只有乙個成員變數就是isa指標,它指向另外乙個物件,指向誰呢?對於乙個物件來說,它的isa指標,就指向自己的類,比如 nsstring *str = [nsstring new]; 那這裡str物件的isa指標就指向nsstring類,當我們向str傳送乙個物件方法的時候,str就通過自己的isa指標,找到nsstring類,再找到這個類中的methodlists,這個列表中就儲存了nsstring類的所有物件方法,找到並呼叫就可以了。

而對於類方法,它是直接被傳送給類的,比如[nsstring alloc],而nsstring類中只儲存了物件方法,不儲存類方法,這又怎麼辦呢,前面說過,類也是物件,也有isa指標,那麼就通過它的isa指標,找到另外乙個類,這個類叫元類,元類儲存了類方法列表,找到它就可以呼叫類方法了。

元類也是有繼承關係的,一子類的元類就繼承自父類的元類,當在自己的類中找不到方法時,就向父類尋找,一直找到nsobject,這也就結識了為什麼每乙個類都可以alloc,new...因為這些是定義在nsobject中的。

元類也是乙個物件,它也有isa指標,所有的元類的isa指標都指向nsobject類的元類,而nsobject元類的isa指標指向自己,下圖反映了這個複雜的關係:

這樣,每個物件在記憶體中就只儲存成員變數和isa指標就可以了,物件方法的實現儲存在類中,物件可以通過isa指標呼叫,類方法儲存在元類中,類可以通過isa指標呼叫,而唯一乙個方法實現和自己儲存在一起的就是nsobject的元類,它的isa指標指向自己。 

OC學習筆記04 理解物件導向

物件導向是相對於面向過程而言的 物件導向和面向過程都是一種思想 面向過程 強調的是功能行為 關注的是解決問題需要哪些步驟 物件導向 將功能封裝進物件,強調具備了功能的物件 關注的是解決問題需要哪些物件 物件導向是基於面向過程的 物件導向的特點 是一種符合人們思考習慣的思想 可以將複雜的事情簡單化 將...

c 物件模型通俗理解

類例項化後該類物件成員記憶體分布情況。有虛函式的類,都會給該類分配乙個虛函式表。在類物件記憶體內 虛函式指標 根據宣告順序的非靜態資料成員 在類物件記憶體外 type info rtti 執行時型別識別 通過rtti,能夠通過基類的指標或引用來檢索其所指物件的實際型別 虛函式表,靜態資料成員,靜態函...

理解文件物件模型(3)

這篇dom說一說飽受爭議window物件,還好window物件已經作為html5的一部分被新增到html規範之中了 1.獲取window 可以使用兩種方法獲取window物件,正規的html5方式是在document物件上使用defaultview屬性 另一種則是使用瀏覽器都支援的全域性變數wind...