「技術專欄」這些年咱們愛着的 Objective-C

文 / 唐天勇 LeanCloud 工程師編程

Objective-C 是開發 OS X 和 iOS 應用的標準語言。即使是每天跟它打交道的開發者,有些也會誤覺得 Objective-C 就是 Apple 公司建立出來的語言,但實際上它並非 Apple 的親骨肉,而是從別人家過繼過來的孩子。閉包

程序設計語言是一個規範,它能夠有許多種實現。在歷史的漫漫長河中也出現過其餘 Objective-C 實現,下面我會主要以 Apple 的 Objective-C 實現來論述。併發

出生

Objective-C 的誕生要追溯到 1980 年左右。那時 Brad Cox 和 Tom Love 兩位工程師還在 ITT 實驗室工做,他們意識到程序設計語言的抽象程度在軟件開發中扮演着重要角色。他們認爲 Smalltalk 在這方面作得很是出色,但執行效率是瓶頸,而且實驗室裏大部分系統軟件都是用 C 語言實現的,所以他們但願把 Smalltalk 的好處帶到 C 語言裏。Objective-C 就是在這樣的背景下誕生了。函數

成長

1983 年,Brad Cox 和 Tom Love 成立了 Stepstone 公司,併發布了第一個 Objective-C 實現。據 Brad Cox 回憶,最初的實現就是個簡單的預處理器。他們使用 sed 和 awk 等工具把 Objective-C 直接翻譯爲 C 語言。可 C 語言並不原生支持 Objective-C 的動態語義,例如 dynamic dispatch。動態語義是經過一個 library 來實現的,這個 library 逐漸發展成瞭如今的 runtime library(簡稱 runtime)。工具

後來 Stepstone 被 Steve Jobs 領導的 NeXT 收購,Objective-C 由此迎來它的首次發展。不過 NeXT 並無在語言中引入新特性,而是對 runtime 作了一些優化,即 NeXT runtime。優化

Apple 收購了老喬的 NeXT 後,就把 NeXT 當時在使用的 Objective-C 直接繼承了過來,即所謂的「Objective-C 1.0」。後來 Apple 在語言中增長了一些新特性,例如屬性、fast enumeration、垃圾回收(後來被 ARC 取代)。不久前 Apple 爲Objective-C 引入了輕量級泛型。這樣的改進可謂進步巨大,runtime 也被徹底重寫並開源了出來。 Apple 將這一新的實現稱爲「Objective-C 2.0」,也就是咱們如今看到的這個樣子。spa

Apple 對語言的持續改進讓開發者歡欣鼓舞。Objective-C 2.0 也在 OS X 和 iOS 應用開發的浪潮中站穩了腳跟。做爲語言的使用者,我對 Objective-C 語言是愛恨交加。一方面,小巧的語言結構、動態的本質讓開發變得多姿多彩,特有的方括號也讓代碼添了幾分味道;另外一方面,從現代的眼光來看,語言缺少一些高級特徵,好比命名空間 namespace、完整的泛型支持等。雖然仍不完美,但承擔起 Apple 應用開發的重擔,它作到了。翻譯

性格

早期的 Objective-C 只支持手動內存管理,開發者必須仔細去跟蹤每一個對象的生命週期,猶如作針線活通常,步步當心謹慎,不然就會扎破手指。而同時期的許多語言都已開始引入了更高級的內存管理,例如垃圾回收,Java 就是其中的典型表明。設計

雖然手動內存管理在執行效率上有優點,但同時也帶來了額外的心智負擔。好在後來引入了自動引用計數 ARC。雖然它的背後仍然是引用計數,但大多數時候不須要開發者跟蹤對象的生命週期,而是交由編譯器和 runtime 來作。開發者只須要注意一些特殊狀況便可,例如循環引用。code

Objective-C 不支持 namespace,也就意味着它不支持嵌套類,全部符號會在編譯階段鏈接到一個全局的 namespace 下。若是鏈接時發現了重複的符號,編譯就會失敗。爲什麼 Apple 遲遲不在 Objective-C 中引入 namespace 呢?

其實 Apple 曾屢次考慮過這個問題,但發現這是個大坑,填起來困難重重。困難之一是與 C 和 C++ 之間的協調。因爲 Apple 容許 Objective-C 和 C++ 混合編程(Objective-C++),這就要求 Objective-C 的 namespace 與 C++ 的保持兼容,然而這是不可能的。

另外一種選擇是隻對 Objective-C 語言實現 namespace,不過也有問題。由於 Objective-C 語言是 C 語言的超集,C 語言沒有 namespace 的概念,其結果只能對 Objective-C 的類實現 namespace。可是 Objective-C 中的那些方法又會最終編譯成 C 語言的函數,只能對方法作 name mangling,這便會形成兼容性的問題。目前 Apple 還沒有找到能完美解決這一問題的方案,Objective-C 也只能先感慨着與 namespace 的緣分未到了。</p>

Objective-C 早期不支持匿名函數或者閉包,但隨着社區的呼聲愈來愈高,Apple 最終爲 Objective-C 增長了這一特性。不過有趣的是, Apple 是直接在 C 語言中實現的,稱之爲 block。Objective-C 擴展了 block,以適應 Objective-C 的內存管理。

Objective-C 1.0 不支持泛型。直到 Objective-C 2.0 才引入了輕量級泛型。注意,之因此輕量級是由於它徹底由編譯器實現,沒有 runtime 參與,泛型信息在代碼生成階段就被丟棄了。可能 Apple 也不但願在 runtime 中引入額外的代價吧。

社區

隨着 OS X 和 iOS 開發生態的繁榮。愈來愈多的開發者投入到 OS X 和 iOS 應用開發中來,社區涌現出許多優秀的第三方庫。

第三方庫不斷積累,包依賴管理亟待解決。可 Apple 並無官方的解決方案。既然沒有官方的,那就本身動手作一個吧,CocoaPods 就是這樣問世的。不過因爲 Xcode 的封閉,CocoaPods 的開發過程也很是艱難,常常因 Xcode 的升級而出現不兼容的情況。但 CocoaPods 最終克服了重重障礙,成爲管理依賴的首選。

社區的不斷壯大讓 Objective-C 長期佔據着 TIOBE 排行榜 前 10 的位子,因此這門古老的語言在 20 世紀依然能綻開耀眼的光芒。

將來

2014 年一聲炮響,Swift 橫空出世,Apple 竭盡全力地向世界宣告着這個親骨肉的到來,而有關繼子 Objective-C 該何去何從的討論也愈演愈烈。

誠然,Swift 解決了 Objective-C 的許多痛點,例如支持 namespace、運算符重載、更輕鬆的內存管理等。我想,Objective-C 不會在短期內離咱們遠去,由於社區中還有大量的 codebase 是用 Objective-C 寫的。而且,Objective-C 與 C / C++ 語言更親近,若是項目中須要和大量 C / C++ 交互,Objective-C 仍然會繼續發揮餘熱。

關於 Swift 的那些事兒,我會在下一篇文章中繼續聊。感謝閱讀!

相關文章
相關標籤/搜索