之前在教程中学习了二维数组,原本里面很多知识点都不甚了解,后来经过一番资料查找,基本上理解透彻了,做个总结吧。
老规矩,先上代码:
class Array2D<T> { let columns: Int let rows: Int var array: Array<T?> init(columns: Int, rows: Int) { self.columns = columns self.rows = rows array = Array<T?>(count:rows * columns, repeatedValue: nil) } subscript(column: Int, row: Int) -> T? { get { return array[(row * columns) + column] } set(newValue) { array[(row * columns) + column] = newValue } } }
其实从整体上看,这个自定义的类和C++中的模板类非常相似,比如用T表示任意的数据类型,只不过在swift里面用到了?来表示optional类型,关于optional和non-optional类型在上一篇博文里面已经有所描述,这里就不再重复了。
写过c/c++的二维数组的,应该不难理解二维数组其实本质还是一维数组,只不过是通过两个参数来确定元素的值。所以在类里面有3个变量,分别是行数,列数和用来存储数据的一维数组。
然后两个函数,一个是init初始化函数,还有一个就是subscript函数,我们分别来中点看一下这两个函数。
init函数
init一个二维数组需要两个参数,行数和列数,前两行代码很简单,把形参中的值传给实例化后的类的两个私有变量,而用来存储数据的数组,就得用到swift原声的array类来建立了。关于swift的array类,更多的内容请猛戳:这里
我们就重点来讲解下array的init(count: repeatedValue:)函数吧
先上代码:
init(count:repeatedValue:) Constructs an array with a given number of elements, each initialized to the same value. Declaration init(count: Int, repeatedValue: T) Discussion The resulting array will have count elements in it, each initialized to the same value provided as the value for repeatedValue. For example: let numericArray = Array(count: 3, repeatedValue: 42) // numericArray is [42, 42, 42] let stringArray = Array(count: 2, repeatedValue: "Hello") // stringArray is ["Hello", "Hello"]从举的两个栗子来说,很容易理解了,count表示数组的大小,repeatedValue就表示初始化的值,这里表示所有的值都是一样的,当我第一次看到这个函数,因为教程里面写到的repeatedValue是nil,我以为是是否允许数组有重复的值呢。知道详细查阅了swift的官方文档后,才正确理解了这个函数的意思。
再一次提醒我,千万不能想当然,不能眼高手低,不清楚的事,一定要翻阅下资料弄清楚了。
subscript函数
当我第一次看到这个函数的时候,又被swift的语法搞糊涂了,->是个什么符号?这个函数虽然从内容上可以理解是可以读或者写的,但是具体是怎么个写法?
后来也是查看了官方文档以后,理解透彻了,想要了解完整的subscript函数,请戳这里
一上去就介绍了关于subscript函数的用法:
Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for setting and retrieval. For example, you access elements in an Array instance as someArray[index] and elements in a Dictionary instance as someDictionary[key]. You can define multiple subscripts for a single type, and the appropriate subscript overload to use is selected based on the type of index value you pass to the subscript. Subscripts are not limited to a single dimension, and you can define subscripts with multiple input parameters to suit your custom type’s needs.
Subscripts enable you to query instances of a type by writing one or more values in square brackets after the instance name. Their syntax is similar to both instance method syntax and computed property syntax. You write subscript definitions with the subscript keyword, and specify one or more input parameters and a return type, in the same way as instance methods. Unlike instance methods, subscripts can be read-write or read-only. This behavior is communicated by a getter and setter in the same way as for computed properties:也就是说,你可以定义subscript函数为读写或者只读模式,我们看到的同时有set和get的是读写模式,如果想要只读模式的,不写get关键字就是了:
As with read-only computed properties, you can drop the get keyword for read-only subscripts: subscript(index: Int) -> Int { // return an appropriate subscript value here }我们继续来看几个用到subscript函数的例子,其实定义是这样定义, 使用的时候,和普通的数组usage一样,一对“[]”就可以了
结构体
struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index } } let threeTimesTable = TimesTable(multiplier: 3) println("six times three is \(threeTimesTable[6])") // prints "six times three is 18"
结构体的subscript函数就是返回输入的参数乘以结构体里的私有变量,所以也很容易理解举得例子的值了。
字典
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] numberOfLegs["bird"] = 2
最后再来看一下 官方文档里面给出的二维数组的源代码,是不是和 教程里面的很像呢?
struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(count: rows * columns, repeatedValue: 0.0) } func indexIsValidForRow(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> Double { get { assert(indexIsValidForRow(row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValidForRow(row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } }
只不过这里的Matrix返回的是double类型的数,而我们的教程里面用到是模板T而已。看到这里应该不用再多解释,关于二维数组的所有内容都一目了然吧?