Objective-C語言的起源

Objective-C與C++、Java等面向對象語言類似,不過很多方面還是有差別的。如果你用過另外一種面向對象的語言,那就能理解Objective-C所用的許多范式和模板。但是語法上還是有陌生感。因為該語言使用了“消息結構”而非“函數調用”。(Objective-C語言由Smalltalk演化而來,后者是消息型語言的鼻祖)

// Objective-C

Object *obj = [Object new];

[obj performWith:parameter1 and:parameter2];

// C++

Object *obj = new Object;

obj->perform(parameter1, parameter2);

區別:消息結構的語言,其運行時所執行的代碼由運行環境來決定,而函數調用的語言,則由編譯器決定。如果示例代碼中調用的函數是多態的,那么在運行時要按照“虛方法表”來查找到底要執行哪個函數實現。但是采用消息結構的語言,無論是否多態,總是在運行期才會去查找所要執行的方法。事實上,編譯器甚至不關心接收消息的對象的什么類型,接收消息的對象問題也要在運行時處理,這個過程叫做“動態綁定”。

Objective-C的重要工作都由“運行期組件”來完成,而不是“編譯器”。使用Objective-C的面向對象特性所需的全部數據結構及函數都是在“運行期組件”里面(全部內存管理方法也在)。“運行期組件”的本質上就是一種和開發者所編代碼相連接的”動態庫“,其代碼能把開發者編寫的所有程序粘合起來。這樣的話,只要更新”運行期組件“,就能提升程序性能。但是在”編譯器“完成的語言,則需要重新編譯代碼,才可以提升性能。

Objective-C是C語言的“超集”,C語言的所有功能在Objective-C中都適用。其中我們要理解C語言的內存模型,這有助于我們理解Objective-C的內存模型和“引用計數”機制的工作原理。

Objective-C語言中的指針是用來指示對象的,聲明一個變量,令其指代某個對象:

NSString *someStr = @"The string";

聲明了一個名為:someStr的變量,類型是:NSString *,也就是說,此變量為指向NSString的指針(指針就是地址)。所有的Objective-C都必須這樣聲明。因為對象所占內存必須分配在“堆空間”,絕不能分配在“棧”上。

someStr變量指向分配在堆里面的某塊內存,其中含有一個NSString對象。如果再創建一個變量,讓它指向同一地址,那么并不拷貝改對象,只是2個變量會同時指向此對象:

NSString *someStr = @"The string";

NSString *anotherStr = someStr;

只有一個NSString實例,卻有2個變量指向此實例,類型都是NSString *。這說明“棧”里分配了2塊內存,每塊的大小能存下一枚指針,且值是一樣的,就是NSString實例的內存地址。

分配在堆中的內存必須直接管理,分配在棧上的用于保存變量的內存則會在其棧幀彈出時自動清理。Objective-C將堆內存管理抽象出來了,不需要malloc和free來分配和釋放對象所占的內存了。Objective-C運行期環境吧這部分工作抽象為一套“內存管理框架”--“引用計數”。

在Objective-C中,有時會遇到定義里沒有“*”的變量,它們可能會使用“棧空間”。這些變量保存的不是Objective-C對象。比如:CoreGraphics框架中的CGRect就是。

struct CGRect {

CGPoint origin;

CGSize size;

}

typedef struct CGRect CGRect;

整個系統框架都在使用這樣的結構體,因為如果改用Objective-C對象的話,性能將會受到影響,因為創建對象需要額外的開銷,例如分配和釋放內存等。如果需要保存int、float、double、char等“非對象型”,那么使用像CGRect這樣的結構體就足夠了。

要點:

1.Objective-C給C語言添加了面向對象的特性,是其超集。Objective-C使用動態綁定的消息結構,也就說,在運行期才會去檢查對象類型。接收一條消息之后,究竟應該執行什么代碼,由運行期環境決定,而不是編譯器。

2.理解C語言的核心概念有助于寫好Objective-C程序,尤其是掌握內存模型與指針。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容