多用字面量語法, 少用與之等價的方法

weixin_34279579發表於2016-04-18

Objective-C以複雜的語法著稱,事實上確實是這樣.不過從Objective-C1.0開始,有一個非常簡單的方式建立NSString物件,那就是"字串字面量",其語法如下:

NSString *str = @"Objective-C is the best programming language";

當然不用這樣的語法的話,就要用常見的alloc及init方法來分配並初始化NSString物件了.在新版的編譯器中,也能用這種字面量語法來宣告NSNumber, NSArray, NSDictionary類的例項.使用字面量語法(literal syntax)可以縮減原始碼的長度,使其可讀性提高.

字面數值

整數, 浮點數, 布林值封入Objective-C物件中.這種情況下,可以使用NSNumber類.
一般做法:

NSNumber *num = [NSNumber numberWithInt:3];

字面量語法:

NSNumber *num = @1;

可以看到,字面量語法更為簡潔.不過它的好處還遠不止這些,能以NSNumber例項表示的所有資料型別都可以使用該語法,例如:

NSNumber *intNum = @3;
NSNumber *floatNum = @3.3f;
NSNumber *doubleNum = @3.33333;
NSNumber *boolNum = @YES;
NSNumber *charNum = @'a';

同時字面量語法也適用於表示式:

int a = 3;
float b = 3.33f;
NSNumber *expressionNum = @(a * b);

用字面量來表示數值十分有用,這樣做可以使NSNumber更為簡潔,以為其中只有數字,沒有其他多餘成分.

字面量陣列

陣列是常用的資料結構,通常建立一個陣列的方法是:

NSArray *array = [NSArray arrayWithObjects:@"one", @"two", @"three"];

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

NSArray *array = @[@"one", @"two", @"three"];

這種做法不僅簡單,而且還有利於運算元組,陣列最常見的操作就是通過某個下標取得對應的物件,如果不適用"字面量語法",通常的做法是:

NSString *string = [array objectAtIndex:0];

適用字面量語法的做法則是:

NSString *string = array[0];

這樣的做法簡單明瞭,更容易理解.也和其他語言中訪問陣列中的某個元素類似.

注意:

使用字面量語法建立陣列時,若陣列元素物件中有nil,則會丟擲異常.因為字面量語法其實是一種"語法糖"(計算機語言中與另外一套語法等效但是開發者使用起來更加方便的語法,語法糖可以使程式的可讀性提高,同時減少程式碼出錯率).其效果等於先建立了一個陣列,然後把方括號中的所有物件都加到這個陣列中.

舉個例子:
id object1 = /* ... */;
id object2 = /* ... */;
id object3 = /* ... */;

NSArray *arrayA = [NSArray arrayWithObjects:object1, object2, object3];
NSArray *arrayB = @[object1, object2, object3];

不妨思考一下:如果object1和object3都指向了有效的Objective-C物件,而object2是nil,會出現什麼情況?如果採用字面量語法,建立arrayB時會丟擲異常(attempt to insert nil object from arrayB[1]),arrayA雖然能建立成功,但是其中只有一個object1物件,原因很簡單:arrayWithObjects:方法會依次處理每個引數,直到發現nil為止.

這個差別表明:使用字面量語法更為安全.丟擲異常令程式終止,這比建立好陣列發現陣列中元素個數不對要好很多.想陣列中插入nil通常說明程式有錯,通過異常可以更快的找個這個錯誤.

字面量字典

"字典"是一種對映型資料結構,可向其中新增鍵值對.OC中通常建立字典的做法是:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                             @"Country" ,@"firstName",
                                             @"Gene", @"lastName",
                                             @[NSNumber numberWitnInt:18], @"age", nil];

這樣寫令程式碼的可讀性不高,因為順序是<物件>, <鍵>.這與通常的理解剛好相反.我們一般理解為"鍵"對映到"物件".然而使用字面量語法:

NSDictionary *dictionary = @{@"firstName" : @"Country", 
                                             @"lastName" : @"Gene"
                                             @"age" : @18};

這樣寫的好處一目瞭然.程式碼可讀性還高.同時還指明:字典中的物件和建都必須是OC物件,所以不能把18直接放到字典中.

同樣用字面量語法建立字典也有一個問題,那就是一旦有值為nil,程式便會丟擲異常.這樣也恰到好處提醒了程式猿們字典中有了空物件.同理"dictionaryWithObjectsAndKeys"則無法做到這一點.

還有一點就是通過鍵值來訪問其值,通常的做法:

NSString *name = [dictionary objectForKey:@"firstName"];

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

NSString *name = dictionary[@"firstName"];
可變陣列和字典

對於可變的陣列和字典,字面量語法不僅能訪問到陣列中某個下標對應的元素或字典中某個鍵對應的元素,還可以通過下標修改對應元素的值.
標準做法:

[mutableArray replaceObjectAtIndex:0 withObject:@"Ben"];
[mutableDictionary setObject:@"Ben" forKey:@"lastName"];

字面量語法:

mutableArray[0] = @"Ben";
mutableDictionary[@"lastName"] = @"Ben";

好處不言自明!

侷限性

俗話說:金無足赤,人無完人.除了字串以外,所建立出來的物件必須屬於Foundation框架才行.如果自定義了這些類的子類,則無法使用字面量語法了.要想建立自定義子類的例項,必須採用"非字面量語法".不過也不建議這麼做.因為NSArray, NSDictionary, NSNumber都是業已定型的"子族",很少有人會從其中自定義子類.真要這麼做也比較麻煩.
使用字面量語法建立出來的字串,陣列,字典物件是不可變的.若想變成可變版本,需要複製一份.

NSMutableArray *mutableArray = [@[@1, @2, @3] mutableCopy];

這麼做會多呼叫一個方法,而且還有再建立一個物件,不過筆者認為"功大於過"!

總結:
  • 應該使用字面量語法來建立字串, 陣列, 數值, 字典.與建立此類物件的常規方法相比這麼做更簡潔明瞭.
  • 應該通過取下標操作來訪問陣列下標或字典中鍵所對應的元素.
  • 用字面量語法建立陣列或字典時,若值為nil, 則會丟擲異常, 因此, 務必確保值裡不包含nil.

相關文章