為什麼說Objective-C很難學?

sunset發表於2014-07-13

作為一個網路上的活躍分子,使用Objective-C的開發者,我收到了許多圍繞Objective-C的提問。這些問題在人們學習Objective-C或者嘗試開發app的時候會不斷跳出來,而且其中的某些問題可能籠統如“Objective-C看起來太難了”也會細緻若“那個‘-’是幹嘛用的啊?”。我要說的是這些其實都是好問題,那麼接下來我就和大家探討一下:相對於Ruby或Java,為什麼某些程式設計師對轉投iOS或者OS X開發會心存畏懼。

語法

先說說程式語言是什麼。所謂程式語言就是一種人可以讀得懂的程式程式碼。一門程式語言通常包含一系列內容:語法(語句書寫和宣告的規則)和語義(以達成某些任務為目標,把語句和宣告有效的結合起來)。

大部分(通常情況下)程式語言在方法呼叫上都是類似C語言的風格,訪問類成員採用.語法。(也就是C中的structs)。雖然這些語言一般都有各自己定義類的方式(Java和C#或C++還是不大相同的),但是追究到語言的諸多細節還都是很相似的。每當人們開始接觸一門新的程式語言的時候,如果它的語法看起來很似曾相識,會讓學習者覺得很舒服。像大多數人都是有C語法背景的,所以要學習一門類C語法的語言的話,第一觀感會很親切。

單從語法角度來看,Objective-C可謂**別具一格**。它的語法太特別了,礙於它語法的另類,很多人沒有耐心去深究它的語義,而它的語義恰恰與C++,Java等語言沒什麼區別。

像Python和Ruby這些所謂”古怪”的語言都更容易上手,僅僅是因為它們可以通過.語法來進行方法呼叫和訪問類成員。而且人們通常能夠迅速習慣用縮排來代替花括號。

當我向別人介紹Objective-C的時候,一般情況下,我會拿它和某個OOP(物件導向程式設計)語言來對比說明。

why objective-c is hard to learn 1

目前來看還OK。也許他們之前知道lisp吧,所以不難理解這句語法。

why objective-c is hard to learn 2

到這句,人們普遍覺得比較難接受,情況也變得不那麼樂觀了。

why objective-c is hard to learn 3

這句可以直接讓人們崩潰了。

那些冒號是啥?太嚇人了!隨後冒出一堆問題:方法是怎麼呼叫的?是通過performAction還是什麼別的方式?方法怎麼過載?

要知道,我們沒有在討論方法,我們說的是訊息(messages)(我也不會去討論他們之間的區別)和selectors,好比上文所呈現的performAction:withTwoParameters。但是,大家已經懶得去了解了。

Objective-C是C的超集,它其實是一門很cool的程式語言,但是由於其自身的某些特點,相較於其他現代程式語言,人們會覺得Objective-C很古老。作為C的超集,Objectivec-C在C的基礎上擴充套件了一系列非常規的特性,這恰恰增加了Objective-C的複雜度。

Objective-C是一門大型語言。下此定義的出發點是:它的語法十分繁複。實際上,蘋果已經在加大對Objective-C瘦身的力度,比如說,雖然速度緩慢但是終究還是完成了標頭檔案去標準C風格的過渡。而且,蘋果還為Objective-C做了不少改進,增加了許多新特性,使得Objective-C的程式碼更加簡練,比如:

  • Synthesizing properties
  • 通過.語法訪問getters/setters
  • 垃圾回收(Garbage Collection)
  • Blocks(閉包closures)
  • ARC(Automatic Reference Counting)
  • 弱引用(Weak references)

所以,雖然語言變得越來越龐大,但是開發編寫程式碼的複雜度反而降低了。

Runtime

Objective-C是動態執行的,可能單單從其與C的淵源這個角度來看這個特性並不那麼直觀。由於不需要直接編寫彙編碼,C語言自身是一門變化較低的語言,鑑於Objective-C是C的超集,我們很容易將Objective-C的穩定性趨向於C,但現實際上,Objective-C是動態執行的且靈活性相當高的語言。Objective-C支援函式柯里化(function currying),支援反射機制,可以在執行時動態地為類新增或移除方法。

除非你之前有接觸過類似Objectivec-C這些特性的程式語言,比如說Ruby或Lisp,否則一時間很難適應Objective-C。但是無需擔憂!有些東西,外表看起來神祕可怕其實本質沒那麼複雜。

Framework

使用Objective-C構建apps完全離不開Cocoa/Cocoa Touch框架。就好像用Ruby開發web應用離不開Rails一樣。

經過經年累月的發展,Cocoa已經變得非常的厚重。不過如前文所說,蘋果最近正在逐漸的為常規iOS開發所依賴的Cocoa Touch框架進行減肥,以降低它的複雜度。即便如此,哪怕要開發的app極其簡單,也還是有許多東西要學,像蘋果的官方文件還有已暴露的各種標頭檔案都是很好的學習資源。就拿UIView中的contentStretch屬性為例,標頭檔案的定義和說明如下:

@property(nonatomic) CGRect contentStretch __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

// animatable. default is unit rectangle {{0,0} {1,1}}

這到底是什麼意思呢?按照我的理解,這個屬性是用來描述可伸縮區域的大小。但是怎麼實現的呢?這個區域是指一個矩形嗎?也許你永遠都不會和這個屬性打交道,但是假如在開發過程中的某個時點和場景下使用這個屬效能夠輕鬆解決你的問題,那個時候你會知道它的存在並能正確的使用它嗎?

Cocoa/Cocoa-Touch是龐大的框架。要真正的駕馭它就只能靠熟能生巧了。但這個熟悉它的過程常常使很多新的學習者退縮。

History

一直以來,蘋果都在不停的推動著圍繞Objective-C語言開發體系的進步,像Objective-C runtime,Cocoa/Cocoa Touch框架以及針對Objective-C的編譯器等一系列更高層面設計的交叉重疊使得Objective-C不僅僅是一個語言這麼簡單。

why objective-c is hard to learn 4

所以當學習Objective-C的時候,不能孤立的去學習這門語言、某些框架、它的執行機制或編譯器,而是要把他們融會貫通。比如說現在Objective-C整合的ARC(Automatic Reference Counting)機制就涉及到了語義(不需要顯示呼叫dealloc了)層面、編譯器層面(顯而易見)、以及對Cocoa/Cocoa Touch框架的命名約定等內容。

上文所提到的圍繞Objective-C的一些列緊密關聯的設計算是其獨有的特點。其他的語言或多或少都會依賴於別的的語言或平臺來執行,比如基於.net執行的Iron Python,不是Java但是卻依賴JVM的Clojure,甚至Ruby和Rails其實都有各自相對獨立的實體和工程。唯一一個比較知名的受Cocoa/Cocoa Touch和Objective-C runtime支撐執行的Mac Ruby,後來也被蘋果停掉後了後續支援。

Objective-C和相關的框架、runtime以及編譯器等等這個體系對其他開發者社群而言是又幾乎是封閉的。

未來

從目前掌握的資訊來看,過去的四年來蘋果一直在嘗試降低Objective-C語言的複雜度。淘汰手動記憶體管理以及C標準標頭檔案,引入更符合當下程式語言潮流的ARC機制,還有通過.語法來訪問屬性的getter/setter方法等等都是為了降低Objective-C的學習成本。但是即便如此,Objective-C仍然是具備一定學習門檻的開發語言,它的熱度完全那些基於Objective-C編寫的熱門iOS應用帶起來的。

相關文章