Objective-C 對象模式深入分析

來源:互聯網
上載者:User

標籤:物件模型   nsobject   對象模式   

The Objective-C object model作為一名Objective-C的軟體開發人員,你可以在不需要理解Objective-C的鼻祖C語言和Objective-C所採用的物件模型的情況下,依然能夠完成許多的工作。事實上,因為這些特性的確很複雜,要去學習這些個物件模型可能會令你感到望而卻步。雖然這個問題的確比較複雜,但是還是有努力去學習它的必要性的,因為你最終還是會需要和Objective-C運行時的情況打交道的,而那個時候理解了物件模型將會協助你更好地解決此類問題。端起一杯茶,或者一杯咖啡,跟著我一起來探索Objective-C的物件模型吧。
對象是類的執行個體看起來這個是很明顯的,但是我們不妨花些時間來認真思考一下當我們說“一個對象是一個類的執行個體”的時候,這句話意味著意味著什麼。以下面的代碼舉例說明。
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];
這個代碼看起來更像是人造的,而不是實際使用需要的一段代碼,但是它對於展示Objective-C運行時的具體工作方式是很重要的。當上述代碼執行完畢後,我們最終擷取到的是一個叫做name的變數,該變數是NSString類的一個執行個體,請細想一下以下知識:
  • 對象(類的執行個體)是用來儲存狀態的
  • 一個對象的狀態儲存在它的執行個體變數內。比如,上述代碼中的name變數分配了一些記憶體用來儲存字串內容"Peter"
  • name變數同時也包含了一個指向它所在的類(NSString)的指標
  • Objective-C裡面,對象不包含任何方法(行為),僅僅儲存著狀態資訊
  • 類只包含方法,不包含任何狀態資訊。這些包含的方法是他們的執行個體能夠響應的方法(即執行個體方法)
  • 為了使得我們清楚一些,我們再重複一遍:對象包含了儲存的狀態(即執行個體變數),而類包含了儲存的行為(方法)
為了使得表述更加具體,我們來看看下面的表徵圖:
執行個體方法圖中藍色的框框表示name變數(類NSString的一個執行個體)。根據所示,讓我們來看一下,如果你向變數name發送length的訊息,那麼會發生什嗎?
NSUInteger len = [name length];
  1. 首先Objective-C會詢問變數name是哪個類的執行個體,因為所有的方法都包含在類裡面,所以從那裡面才能開始尋找方法length在哪。
  2. 因為name是類NSString的執行個體變數,所以Objective-C將會先找到類NSString,然後開始尋找方法length。
  3. 如果Objective-C在類NSString裡面找到了方法length,那麼它就會停止尋找並開始執行方法。否則,它就會根據類的繼承關係繼續尋找。
需要說明一點的是,上面所描述的過程是經過我的簡化的,我沒有考慮方法儲存的其他情況。(比如Objective-C的分類)

類也是對象既然類能夠儲存它的執行個體的方法(執行個體方法),那麼類方法儲存在哪裡呢?我們再來看看建立變數name的代碼:
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];
上述代碼中,訊息stringWithFormat:是向類NSString發送的。類可以接收訊息嗎?如果可以,那麼那些方法儲存在哪裡呢?事實上是這樣的,Objective-C的文法隱藏了一些東西,他隱藏了類也是對象的事實。如果類NSString是一個對象,那就意味著它一定是從一個儲存著它的方法的類執行個體化來的。這個猜測是對的,不過在深入這個問題之前,我們再來看一段代碼:
@interface Person : NSObject {}+ (void) aClassMethod;- (void) anInstanceMethod;@end
也許你看過這種類似的代碼很多很多,但是這這段代碼幹嘛的?
  • 聲明了一個類,該類是Person
  • 這個類用來儲存執行個體方法
  • 在這段代碼的背後也建立了另外的一個類,不幸的是這個額外的類名也是Person,只不過它是Person元類而已
  • Person元類會儲存著Person的類方法
看起來現在的問題越來越複雜了,因為相同的名字用了一遍又一遍,回到最初的變數name上來討論,我們可以說:
  • 變數name是類NSString的一個執行個體
  • 類NSString是一個NSString元類執行個體化的一個對象
  • 如果你向對象name發送訊息length,那麼Objective-C會去類NSString尋找這個方法
  • 如果你向對象NSString發送stringWithFormate:訊息,Objective-C會在NSString元類裡面尋找這個方法
  • NSString是一個類,也是一個對象,類也是一個對象
這裡是另外一個類圖
元類方法(類方法)圖這一次,藍色的框框表示的是NSString對象,我們再來看看建立name對象的代碼:
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];
當向對象NSString發送訊息stringWithFormate:的時候,Objective-C將會:
  1. 詢問NSString對象是哪個類的一個執行個體,哪一個是它的元類
  2. 開始在NSString的元類裡面尋找方法stringWithFormate:,如果沒找到,它會繼續根據類的類的繼承關係繼續尋找
當然,因為NSString繼承自NSObject,所以NSString元類繼承自NSObject元類。
奇怪的NSObject繼承如果到了這裡你還算清醒的話,那麼利用你現在所掌握的關於Objective-C物件模型的知識夠你去瞭解你的代碼在運行時會發生了什麼。可能還有一個問題你想知道:為了麼NSObject元類好像繼承自NSObject類?這是因為本來就是這樣子的。考慮一下以下情況:
  • NSObject為它的執行個體儲存著方法(儲存執行個體方法)
  • NSObject元類為類NSObject儲存著方法。(儲存類方法)
  • NSObject元類繼承自非元類NSObject
  • 因此,NSObject的執行個體方法也是類方法,這些方法在所有Objective-C的元類方法的尋找路徑中
有點奇怪,但是如果你再去看看上面的圖,你就應該會更清楚些了。

Objective-C 對象模式深入分析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.