第三章——集合(数组与可变性)

本文介绍了Swift语言中数组的基本概念及使用方法,包括数组的创建、常用操作如append、isEmpty等,并探讨了数组的可变性及其与Objective-C中NSArray的区别。

我们在swift中最常用的集合类型就是数组了。数组,简单来说,就是一列东西。比如我们可以这样创建一个数字的数组:

let fibs = [0, 1, 1, 2, 3, 5]
复制代码

数组有一些常用操作,比如isEmptycout方法1,分别获取数组的第一个和最后一个元素(除非数组为空)。数组还允许使用下标脚本(subscript),通过指定一个下标直接访问元素。但使用下标脚本是不安全的操作,因为在获取元素之前,你需要确保下标没有越界,否则程序就会崩溃。

如果我们想要修改刚刚定义的数组(比如使用apppend方法),我们会得到一个编译错误。这是因为通过let关键字,数组被定义为了常量(constant)。在很多情况下这么做毫无问题,因为它可以防止你偶然间修改到这个数组。我们需要使用var关键字来让这个数组成为一个变量(variable)。

var mutableFibs = [0, 1, 1, 2, 3, 5]
复制代码

这样就容易在数组后追加一个或一组元素了:

mutableFibs.append(8)
mutableFibs.appendContentsOf([13,21])
复制代码

varlet区别开来有很多好处。被定义为let的变量不能被改变,因此它更容易理解。当你读到类似于let fibs = ……的时候,你就知道编译器会保证fibs的值永远不会变。这极大的帮助我们通读整篇代码。需要注意的是当变量表示一个对象时,它的值是一个指针。用let来定义一个对象可以保证这个指针所指向的内存地址是不变的,但是它指向的内存中的数据是可能会改变的(也就是说实例变量)2。我们会在第四章中更加深入的理解结构体和类的区别。

Swift中的数组有自己的值语义。具体说来就是数组中的值从来不会共享。当创建一个新的数组变量,然后把旧的数组赋值给它时,其实是把旧的数组变量复制了一份,把数组作为参数传给函数中也是如此。比如在下面的代码段中,x不会被修改。

var x = [1,2,3]
var y = x
y.append(4)
复制代码

var y = x这句代码把x复制了一份,所以在y的末尾追加一个4不会对x有任何影响,x的值依然是[1,2,3]

对比一下NSArray采用的实现可变性的方法,NSArray没有变异方法(mutating method),需要用NSMutableArray来让一个数组变成可变的。

但只是有一个不可变的NSArray引用并不意味着数组就不能在你眼皮子底下被改变。

let a = NSMutableArray(array: [1,2,3])

// 我不想让b能被改变
let b: NSArray = a

// 但其实b还是可以被改变 —— 通过a
a.insertObject(4, atIndex:3)

// 现在b也含有4了
print(b)
复制代码

正确的做法是在创建b的时候把a拷贝一份:

let a = NSMutableArray(array: [1,2,3])

// 我不想让b能被改变
let b: NSArray = a.copy() as! NSArray

a.insertObject(4, atIndex:3)
print(b)  // b现在依然还是[1,2,3]

复制代码

在上面的例子中,我们显然需要把a复制一份,因为毕竟a自己是可变的。虽然在方法间传递数组的情况不太常见、但这会导致很多不必要的复制。

在Swift中,我们不需要NSArrayNSMutableArray这两种数组了,只需要一个Swift自己的数组便足矣。数组的可变性由varlet关键字来决定。与OC不同的是,对某一个数组的引用是不会共享的,也就是当你用let来定义第二个数组的时候,你可以确保这第二个数组是不会改变的。

确实,经常复制数组会带来性能上的问题,但实际上,Swift标注库里所有的集合类型在实现时都采用了“写时复制(copy-on-write)”技术以确保数据只有在真正需要的时候才会被复制。所以在之前的例子中,xyy.append(4)调用之前,其实共享了同一块内部存储区域。在“Mutability”章节我们会深入了解数组的值语义,包括如何为自定义的类型实现“写时复制”技术

#译者注

[1]:我觉得严格来说是isEmptycout属性的get方法。

[2]:也就说object.attribute = newValue可以,而object = newObject不可以。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值