這些年我們愛着的Objective-C

雷鋒網 於 26/06/2016 發表 收藏文章
雷鋒網(搜索“雷鋒網”公眾號關注)按:本文作者唐天勇。歡迎關注其知乎專欄“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」,也就是我們現在看到的這個樣子。

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



性格

早期的Objective-C只支持手動內存管理,開發者必須仔細去跟蹤每個對象的生命週期,猶如做針線活一般,步步小心謹慎,否則就會扎破手指。而同時期的許多語言都已開始引入了更高級的內存管理,例如垃圾回收,Java就是其中的典型代表。雖然手動內存管理在執行效率上有優勢,但同時也帶來了額外的心智負擔。好在後來引入了自動引用計數ARC。雖然它的背後仍然是引用計數,但大多數時候不需要開發者跟蹤對象的生命週期,而是交由編譯器和runtime來做。開發者只需要注意一些特殊情況即可,例如循環引用。

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,這又會導致ABI不兼容。目前Apple尚未找到能完美解決這一問題的方案,Objective-C也只能先感慨着與namespace的緣分未到了。

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的位子,所以這門古老的語言在21世紀依然能綻放耀眼的光芒。



未來

2014年一聲炮響,Swift橫空出世,Apple不遺餘力地向世界宣告着這個親骨肉的到來,而有關繼子Objective-C該何去何從的討論也愈演愈烈。誠然,Swif 解決了Objective-C的許多痛點,例如支持namespace、運算符重載、更輕鬆的內存管理等。我想,Objective-C不會在短時間內離我們遠去,因為社區中還有大量的codebase是用Objective-C寫的。並且,Objective-C與 C / C++語言更親近,如果項目中需要和大量 C / C++交互,Objective-C 仍然會繼續發揮餘熱。

資料來源:雷鋒網
作者/編輯:唐天勇

留言


請按此登錄後留言。未成為會員? 立即註冊
    快捷鍵:←
    快捷鍵:→