字面量 - 语法糖

原创 2015年12月19日 20:56:56

编写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’;

字面量语法也适用于下述表达式:

int x = 5;

float y = 6.32f;

NSNumber *expressionNumber = @(x * y);

以字面量来表示数值十分有用。这样做可以令NSNumber对象变得整洁,因为声明中只包含数值,而没有多余的语法成分。

字面量数组

数组是常用的数据结构。如果不使用字面量语法,那么就要这样来创建数组:

NSArray *animals =

[NSArray arrayWithObjects:@"cat", @"dog",

                         @"mouse", @"badger", nil];

而使用字面量语法来创建则是:

NSArray *animals = @[@"cat", @"dog", @"mouse", @"badger"];

上面这种做法不仅简单,而且还利于操作数组。数组的常见操作就是取某个下标所对应的对象,这用字面量来做更为容易。如果不用字面量,那么通常会用“objectAtIndex:”方法:

NSString *dog = [animals objectAtIndex:1];

若使用字面量,则是:

NSString *dog = animals[1];

这也叫做“取下标”操作(subscripting),与使用字面量语法的其他情况一样,这种方式也更为简洁、更易理解,而且与其他语言中依下标来访问数组元素时所用的语法类似。

不过,用字面量语法创建数组时要注意,若数组元素对象中有nil,则会抛出异常,因为字面量语法实际上只是一种“语法糖”(syntactic sugar),其效果等于是先创建了一个数组,然后把方括号内的所有对象都加到这个数组中。抛出的异常会是这样:

*** Terminating app due to uncaught exception

'NSInvalidArgumentException', reason: '***

-[__NSPlaceholderArray initWithObjects:count:]: attempt to

insert nil object from objects[0]'

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

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。
版权声明:VIC

BLOCK/字面量(语法糖)OC——第六天

1、//block ,块语法,实质是匿名函数,是对C语言中函数的扩充,扩展;     //block  语法可以用来保存一段代码或者用来调用一段封装好的代码;     //block  语法由于是...
  • qq_31810357
  • qq_31810357
  • 2015年10月08日 09:05
  • 798

C语言的一个语法糖

请看语法糖的一个定义语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程)创造的一个词语,它意指那...
  • qq_26772049
  • qq_26772049
  • 2016年03月22日 22:51
  • 490

python的一些语法糖

1   Python中if-else语句的多种写法 a, b, c = 1, 2, 3 1.常规 if a>b:     c = a else:  ...
  • crazyhacking
  • crazyhacking
  • 2014年05月21日 17:23
  • 5461

几个 Python 语法糖的实现

受这位小哥(https://github.com/czheo/syntax_sugar_python)的启发,我照着它的 Usage 实现了一部分语法糖。1. compose实现compose函数,满...
  • wizardforcel
  • wizardforcel
  • 2017年01月21日 15:51
  • 817

深入理解java虚拟机(十二) Java 语法糖背后的真相

语法糖(Syntactic Sugar),也叫糖衣语法,是英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语。指的是,在计算机语言中添加某种语法,这种语法能使程序员更方便...
  • zq602316498
  • zq602316498
  • 2014年09月05日 23:40
  • 2276

Swift语法糖的使用

Swift语法糖的使用 语法糖的简介 语法糖Selector例子 语法糖的简介语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Land...
  • fire_niao
  • fire_niao
  • 2016年06月14日 10:55
  • 1082

VUE字面量语法

在使用props进行计算时一定要注意,运算的数字还是字符串或其他特殊性字符,在这里我们演示一下,运算时数字和字符串的情况。实例: ...
  • qq_24147051
  • qq_24147051
  • 2016年09月02日 16:01
  • 836

OC中的语法糖(你真的理解了点语法么?)

语法糖是一种大多程序员开发的时候使用的东西,今天我们一起来研究下OC中的语法糖。...
  • miscellaner
  • miscellaner
  • 2015年01月23日 17:11
  • 1350

【Basic Code】原来这就是“语法糖”

前些天技术总监在给几位Android工程师做C#培训时,提到了一个“语法糖”的概念,组长问我,你知道“语法糖”吗?我用“一脸懵逼”的神情予以这个大男孩回复,啊哈哈,后来查了查,原来这就是“语法糖”啊。...
  • u013047584
  • u013047584
  • 2016年11月06日 12:26
  • 2488

PHP的面向对象语法糖

语法糖在很多国内编程语言译著里指为方便实现某种设计提供的语法上的特性。 最近看了一本PHP设计模式书里介绍PHP为面向对象提供的语法特性的章节,为了做个小总结与注明和以前用的编程语言的区别,做个记录...
  • old_imp
  • old_imp
  • 2013年01月02日 15:45
  • 2755
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字面量 - 语法糖
举报原因:
原因补充:

(最多只允许输入30个字)