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