数组遭受了不平等对待吗?
在我们访问数组的时候,如果发生了越界,那么我们一定会收到错误。以swift语言为例。
let array = [1,2,3]
array[10] // error !!!!!!!!!
数组中只包含三个元素,但我们用下标10去访问,发生越界错误。
但是当我们访问一个不在字典中的元素的时候,确不会发生类似的情况!
let dic = ["a": 1, "b": 2]
dic["z"] // 虽然不存在,但不会出现异常
同样的问题,不同的待遇,这是为啥呢?
究其原因
我们来查看一下swift中数组和字典下标访问的实现。
struct Array<Element> {
subscript(index: Int) -> Element
}
struct Dictionary<Key: Hashable, Value> {
subscript(key: Key) -> Value?
}
比较两者的实现,我们可以得到问题的原因:
- 数组下标访问返回的不是一个optional类型
- subscript方法无法throw错误
所以对于数组而言,swift除了弄个fatalError以外,没有其它的替代方案了。而字典返回的是optional类型值,如果发生什么意外状况,即使subscript不能throw errors,字典也可以悠然的返回一个nil。
让我们定义另个版本
其实我们可以给数组做一个扩展,实现一个即使数组访问越界也不会抛异常的版本。
extension Array {
subscript(safe index: Int) -> Element? {
return index >= 0 && index < count ? self[index] : nil
}
}
我们使用 extension 关键字来给Array做一个扩展,要注意的是:我们无法覆盖原有的subscript方法,
注意:subscript方法是可以被重载的,也就是说允许同时有多个subscript方法存在
我们只增加一个新的subscript方法,并明确指定一个外部参数就可以了,我们现在可以这样访问数组了。
var array = [1,2,3]
array[safe: 10] // 返回nil,而不是异常
我们需要在下标访问的时候增加一个label,这个时候虽然我们越界了,但我们却像字典那样,收获了一个nil。
本文的目的是讨论一下字典与数组下标实现的区别以及subscript的一些特点:不可throw,可以重载等
但绝对不是在说数组越界后应该不应该抛出异常。抛不抛出异常要从数组的数据结构应用场景等多方面考虑。