2
本文作者: 唐天勇 | 2016-06-25 23:06 |
雷鋒網(wǎng)按:本文作者唐天勇, iOS研發(fā)工程師。歡迎關(guān)注其知乎專欄“LeanCloud技術(shù)專欄”。
Objective-C是開發(fā)OS X和iOS應(yīng)用的標準語言。即便是天天跟它打交道的開發(fā)者,有些也會誤以為Objective-C就是Apple公司創(chuàng)建出來的語言,但實際上它并不是Apple的親骨肉,而是從別人家過繼過來的孩子。
程序設(shè)計語言是一個規(guī)范,它可以有許多種實現(xiàn)。在歷史的漫漫長河中也出現(xiàn)過其他Objective-C實現(xiàn),下面我會主要以Apple的Objective-C實現(xiàn)來論述。
Objective-C的誕生要追溯到1980年左右。那時Brad Cox和Tom Love兩位工程師還在ITT實驗室工作,他們意識到程序設(shè)計語言的抽象程度在軟件開發(fā)中扮演著重要角色。他們認為Smalltalk在這方面做得非常出色,但執(zhí)行效率是瓶頸,并且實驗室里大部分系統(tǒng)軟件都是用C語言實現(xiàn)的,因此他們希望把Smalltalk的好處帶到C語言里。Objective-C就是在這樣的背景下誕生了。
1983 年,Brad Cox和Tom Love成立了Stepstone公司,并發(fā)布了第一個Objective-C實現(xiàn)。據(jù)Brad Cox回憶,最初的實現(xiàn)就是個簡單的預(yù)處理器。他們使用sed和awk等工具把Objective-C直接翻譯為C語言??蒀語言并不原生支持Objective-C的動態(tài)語義,例如dynamic dispatch。動態(tài)語義是通過一個library來實現(xiàn)的,這個library逐漸發(fā)展成了現(xiàn)在的runtime library(簡稱 runtime)。
后來Stepstone被Steve Jobs領(lǐng)導(dǎo)的NeXT收購,Objective-C由此迎來它的首次發(fā)展。不過NeXT并沒有在語言中引入新特性,而是對runtime做了一些優(yōu)化,即NeXT runtime。
Apple收購了老喬的NeXT后,就把NeXT當(dāng)時在使用的Objective-C直接繼承了過來,即所謂的「Objective-C 1.0」。后來Apple在語言中增加了一些新特性,例如屬性、fast enumeration、垃圾回收(后來被ARC取代)。不久前Apple為Objective-C引入了輕量級泛型。這樣的改進可謂進步巨大,runtime也被完全重寫并開源了出來。 Apple將這一新的實現(xiàn)稱為「Objective-C 2.0」,也就是我們現(xiàn)在看到的這個樣子。
Apple對語言的持續(xù)改進讓開發(fā)者歡欣鼓舞。Objective-C 2.0也在OS X和iOS應(yīng)用開發(fā)的浪潮中站穩(wěn)了腳跟。作為語言的使用者,我對Objective-C語言是愛恨交加。一方面,小巧的語言結(jié)構(gòu)、動態(tài)的本質(zhì)讓開發(fā)變得多姿多彩,特有的方括號也讓代碼添了幾分味道;另一方面,從現(xiàn)代的眼光來看,語言缺乏一些高級特征,比如命名空間 namespace、完整的泛型支持等。雖然仍不完美,但承擔(dān)起Apple應(yīng)用開發(fā)的重擔(dān),它做到了。
早期的Objective-C只支持手動內(nèi)存管理,開發(fā)者必須仔細去跟蹤每個對象的生命周期,猶如做針線活一般,步步小心謹慎,否則就會扎破手指。而同時期的許多語言都已開始引入了更高級的內(nèi)存管理,例如垃圾回收,Java就是其中的典型代表。雖然手動內(nèi)存管理在執(zhí)行效率上有優(yōu)勢,但同時也帶來了額外的心智負擔(dān)。好在后來引入了自動引用計數(shù)ARC。雖然它的背后仍然是引用計數(shù),但大多數(shù)時候不需要開發(fā)者跟蹤對象的生命周期,而是交由編譯器和runtime來做。開發(fā)者只需要注意一些特殊情況即可,例如循環(huán)引用。
Objective-C不支持namespace,也就意味著它不支持嵌套類,所有符號會在編譯階段連接到一個全局的namespace下。如果連接時發(fā)現(xiàn)了重復(fù)的符號,編譯就會失敗。為何Apple遲遲不在Objective-C中引入namespace呢?其實Apple曾多次考慮過這個問題,但發(fā)現(xiàn)這是個大坑,填起來困難重重。
困難之一是與C和C++之間的協(xié)調(diào)。由于Apple允許Objective-C和C++混合編程(Objective-C++),這就要求Objective-C的namespace與C++的保持兼容,然而這是不可能的。另一種選擇是只對Objective-C語言實現(xiàn)namespace,不過也有問題。因為Objective-C語言是C語言的超集,C語言沒有namespace的概念,其結(jié)果只能對Objective-C的類實現(xiàn)namespace。但是Objective-C中的那些方法又會最終編譯成C語言的函數(shù),只能對方法做name mangling,這又會導(dǎo)致ABI不兼容。目前Apple尚未找到能完美解決這一問題的方案,Objective-C也只能先感慨著與namespace的緣分未到了。
Objective-C早期不支持匿名函數(shù)或者閉包,但隨著社區(qū)的呼聲越來越高,Apple最終為Objective-C增加了這一特性。不過有趣的是, Apple是直接在C語言中實現(xiàn)的,稱之為block。Objective-C擴展了block,以適應(yīng)Objective-C的內(nèi)存管理。
Objective-C 1.0不支持泛型。直到Objective-C 2.0才引入了輕量級泛型。注意,之所以輕量級是因為它完全由編譯器實現(xiàn),沒有runtime參與,泛型信息在代碼生成階段就被丟棄了。可能Apple也不希望在runtime中引入額外的代價吧。
隨著OS X和iOS開發(fā)生態(tài)的繁榮。越來越多的開發(fā)者投入到OS X和iOS應(yīng)用開發(fā)中來,社區(qū)涌現(xiàn)出許多優(yōu)秀的第三方庫。
第三方庫不斷積累,包依賴管理亟待解決??葾pple并沒有官方的解決方案。既然沒有官方的,那就自己動手做一個吧,CocoaPods就是這樣問世的。不過由于Xcode的封閉,CocoaPods的開發(fā)過程也非常艱難,經(jīng)常因Xcode的升級而出現(xiàn)不兼容的狀況。但CocoaPods最終克服了重重障礙,成為管理依賴的首選。
社區(qū)的不斷壯大讓Objective-C長期占據(jù)著TIOBE排行榜前10的位子,所以這門古老的語言在21世紀依然能綻放耀眼的光芒。
2014年一聲炮響,Swift橫空出世,Apple不遺余力地向世界宣告著這個親骨肉的到來,而有關(guān)繼子Objective-C該何去何從的討論也愈演愈烈。誠然,Swif 解決了Objective-C的許多痛點,例如支持namespace、運算符重載、更輕松的內(nèi)存管理等。我想,Objective-C不會在短時間內(nèi)離我們遠去,因為社區(qū)中還有大量的codebase是用Objective-C寫的。并且,Objective-C與 C / C++語言更親近,如果項目中需要和大量 C / C++交互,Objective-C 仍然會繼續(xù)發(fā)揮余熱。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。