淺析Objective-C字面量

編寫Objective-C程序時,總會用到某幾個類,它們屬於Foundation框架。雖然從技術上來說,不用Foundation框架也能寫出Objective-C代碼,但實際上卻經常要用到此框架。這幾個類是NSString、NSNumber、NSArray、NSDictionary。從類名上即可看出各自所表示的數據結構。

Objective-C以語法繁雜而著稱。事實上的確是這樣。不過,從Objective-C 1.0起,有一種非常簡單的方式能創建NSString對象。這就是“字符串字面量”(string literal),其語法如下:
NSString *someString = @”Effective Objective-C 2.0”;

如果不用這種語法的話,就要以常見的alloc及init方法來分配並初始化NSString對象了。在版本較新的編譯器中,也能用這種字面量語法來聲明NSNumber、NSArray、NSDictionary類的實例。使用字面量語法(literal syntax)可以縮減源代碼長度,使其更爲易讀。

字面數值

有時需要把整數、浮點數、布爾值封入Objective-C對象中。這種情況下可以用NSNumber類,該類可處理多種類型的數值。若是不用字面量,那麼就需要按下述方式創建實例:
NSNumber *someNumber = [NSNumber numberWithInt:1];

上面這行代碼創建了一個數字,將其值設爲整數1。然而使用字面量能令代碼更爲整潔:
NSNumber *someNumber = @1;

大家可以看到,字面量語法更爲精簡。不過它還有很多好處。能夠以NSNumber實例表示的所有數據類型都可使用該語法。例如:
NSNumber intNumber = @1;
NSNumber 
floatNumber = @2.5f;

NSNumber doubleNumber = @3.14159;
NSNumber 
boolNumber = @YES;

NSNumber *charNumber = @’a’;

字面量語法也適用於下述表達式:

 

以字面量來表示數值十分有用。這樣做可以令NSNumber對象變得整潔,因爲聲明中只包含數值,而沒有多餘的語法成分。

字面量數組

數組是常用的數據結構。如果不使用字面量語法,那麼就要這樣來創建數組:

 

 

而使用字面量語法來創建則是:

 

 

上面這種做法不僅簡單,而且還利於操作數組。數組的常見操作就是取某個下標所對應的對象,這用字面量來做更爲容易。如果不用字面量,那麼通常會用“objectAtIndex:”方法:

 

若使用字面量,則是:

 

這也叫做“取下標”操作(subscripting),與使用字面量語法的其他情況一樣,這種方式也更爲簡潔、更易理解,而且與其他語言中依下標來訪問數組元素時所用的語法類似。

不過,用字面量語法創建數組時要注意,若數組元素對象中有nil,則會拋出異常,因爲字面量語法實際上只是一種“語法糖”(syntactic sugar),其效果等於是先創建了一個數組,然後把方括號內的所有對象都加到這個數組中。拋出的異常會是這樣:

1
2
3
4
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '***
-[__NSPlaceholderArray initWithObjects:count:]: attempt to
insert nil object from objects[0]'

 

在改用字面量語法來創建數組時就會遇到這個問題。下面這段代碼分別以兩種語法創建數組:

1
2
3
4
5
6
7
id object1 = /* ... */;
id object2 = /* ... */;
id object3 = /* ... */;

NSArray *arrayA = [NSArray array WithObjects:
                       object1, object2, object3, nil];
NSArray *arrayB = @[object1, object2, object3];

 

大家想想:如果object1與object3都指向了有效的Objective-C對象,而object2是nil,那麼會出現什麼情況呢?按字面量語法創建數組arrayB時會拋出異常。arrayA雖然能創建出來,但是其中卻只含有object1一個對象。原因在於,“arrayWithObjects:”方法會依次處理各個參數,直到發現nil爲止,由於object2是nil,所以該方法會提前結束。

這個微妙的差別表明,使用字面量語法更爲安全。拋出異常令應用程序終止執行,這比創建好數組之後才發現元素個數少了要好。向數組中插入nil通常說明程序有錯,而通過異常可以更快地發現這個錯誤。

字面量字典

“字典”(Dictionary)是一種映射型數據結構,可向其中添加鍵值對。與數組一樣,Objective-C代碼也經常用到字典。其創建方式如下:

 

這樣寫令人困惑,因爲其順序是<對象>,<鍵>,<對象>,<鍵>。這與通常理解的順序相反,我們一般認爲是把“鍵”映射到“對象”。因此,這種寫法不容易讀懂。如果改用字面量語法,就清晰多了:

 

上面這種寫法更簡明,而且鍵出現在對象之前,理解起來較順暢。此範例代碼還說明了使用字面量數值的好處。字典中的對象和鍵必須都是Objective-C對象,所以不能把整數28直接放進去,而要將其封裝在NSNumber實例中才行。使用字面量語法很容易就能做到這一點,只需給數字前加一個@字符即可。

與數組一樣,用字面量語法創建字典時也有個問題,那就是一旦有值爲nil,便會拋出異常。不過基於同樣的原因,這也是個好事。假如在創建字典時不小心用了空值對象,那麼“dictionaryWithObjectsAndKeys:”方法就會在首個nil之前停下,並拋出異常,這有助於查錯。

字典也可以像數組那樣用字面量語法訪問。按照特定鍵訪問其值的傳統做法是:

 

與之等效的字面量語法則是:

 

這樣寫也省去了冗贅的語法,令此行代碼簡單易讀。

可變數組與字典

通過取下標操作,可以訪問數組中某個下標或字典中某個鍵所對應的元素。如果數組與字典對象是可變的(mutable),那麼也能通過下標修改其中的元素值。修改可變數組與字典內容的標準做法是:

 

若換用取下標操作來寫,則是:

 

侷限性

字面量語法有個小小的限制,就是除了字符串以外,所創建出來的對象必須屬於Foundation框架才行。如果自定義了這些類的子類,則無法用字面量語法創建其對象。要想創建自定義子類的實例,必須採用“非字面量語法”(nonliteral syntax)。然而,由於NSArray、NSDictionary、NSNumber都是業已定型的“子族”(class cluster,參見第9條),因此很少有人會從其中自定義子類,真要那樣做也比較麻煩。而且一般來說,標準的實現已經很好了,無須再改動。創建字符串時可以使用自定義的子類,然而必須要修改編譯器的選項才行。除非你明白這樣做的後果,否則不鼓勵使用此選項,用NSString就足夠了。

使用字面量語法創建出來的字符串、數組、字典對象都是不可變的(immutable)。若想要可變版本的對象,則需複製一份:

 

 

這麼做會多調用一個方法,而且還要再創建一個對象,不過使用字面量語法所帶來的好處還是多於上述缺點的。

要點

應該使用字面量語法來創建字符串、數值、數組、字典。與創建此類對象的常規方法相比,這麼做更加簡明扼要。

應該通過取下標操作來訪問數組下標或字典中的鍵所對應的元素。

 

用字面量語法創建數組或字典時,若值中有nil,則會拋出異常。因此,務必確保值裏不含nil。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章