首页 > ios > 第3条:多用字面量语法,少用与之等价的方法(2)

第3条:多用字面量语法,少用与之等价的方法(2)

  在改用字面量语法来创建数组时就会遇到这个问题。下面这段代码分别以两种语法创建数组:

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代码也经常用到字典。其创建方式如下:

NSDictionary *personData =
    [NSDictionarydictionaryWithObjectsAndKeys:
        @"Matt", @"firstName",
        @"Galloway", @"lastName",
        [NSNumber numberWithInt:28], @"age",
        nil]; 

  这样写令人困惑,因为其顺序是<对象>,<键>,<对象>,<键>。这与通常理解的顺序相反,我们一般认为是把“键”映射到“对象”。因此,这种写法不容易读懂。如果改用字面量语法,就清晰多了:

NSDictionary *personData =
    @{@"firstName" : @"Matt",
      @"lastName" : @"Galloway",
      @"age" : @28}; 

  上面这种写法更简明,而且键出现在对象之前,理解起来较顺畅。此范例代码还说明了使用字面量数值的好处。字典中的对象和键必须都是Objective-C对象,所以不能把整数28直接放进去,而要将其封装在NSNumber实例中才行。使用字面量语法很容易就能做到这一点,只需给数字前加一个@字符即可。
  与数组一样,用字面量语法创建字典时也有个问题,那就是一旦有值为nil,便会抛出异常。不过基于同样的原因,这也是个好事。假如在创建字典时不小心用了空值对象,那么“dictionaryWithObjectsAndKeys:”方法就会在首个nil之前停下,并抛出异常,这有助于查错。
  字典也可以像数组那样用字面量语法访问。按照特定键访问其值的传统做法是:

NSString *lastName = [personData objectForKey:@"lastName"]; 

  与之等效的字面量语法则是:

NSString *lastName = personData[@"lastName"]; 

  这样写也省去了冗赘的语法,令此行代码简单易读。

可变数组与字典

  通过取下标操作,可以访问数组中某个下标或字典中某个键所对应的元素。如果数组与字典对象是可变的(mutable),那么也能通过下标修改其中的元素值。修改可变数组与字典内容的标准做法是:

[mutableArray replaceObjectAtIndex:1 withObject:@"dog"];
[mutableDictionary setObject:@"Galloway"forKey:@"lastName"]; 

  若换用取下标操作来写,则是:

mutableArray[1] = @"dog";
mutableDictionary[@"lastName"] = @"Galloway"; 

局限性

  字面量语法有个小小的限制,就是除了字符串以外,所创建出来的对象必须属于Foundation框架才行。如果自定义了这些类的子类,则无法用字面量语法创建其对象。要想创建自定义子类的实例,必须采用“非字面量语法”(nonliteral syntax)。然而,由于NSArray、NSDictionary、NSNumber都是业已定型的“子族”(class cluster,参见第9条),因此很少有人会从其中自定义子类,真要那样做也比较麻烦。而且一般来说,标准的实现已经很好了,无须再改动。创建字符串时可以使用自定义的子类,然而必须要修改编译器的选项才行。除非你明白这样做的后果,否则不鼓励使用此选项,用NSString就足够了。
  使用字面量语法创建出来的字符串、数组、字典对象都是不可变的(immutable)。若想要可变版本的对象,则需复制一份:

NSMutableArray *mutable = [@[@1, @2, @3, @4, @5] mutableCopy];

这么做会多调用一个方法,而且还要再创建一个对象,不过使用字面量语法所带来的好处还是多于上述缺点的。

要点

  应该使用字面量语法来创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要。
  应该通过取下标操作来访问数组下标或字典中的键所对应的元素。
  用字面量语法创建数组或字典时,若值中有nil,则会抛出异常。因此,务必确保值里不含nil。

  1. 还没有评论
评论提交中, 请稍候...

留言


可以使用的标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Trackbacks & Pingbacks ( 0 )
  1. 还没有 trackbacks