Swift下标
参考:
下标
定义下标:
subscript(parameterList) -> ReturnType {
get {
// return someValue of ReturnType
}
set (newValue) {
// set someValue of ReturnType to newValue
}
}
Subscript
的定义混合了function
和计算属性的语法:
1.第一部分类似于一个函数的定义,有参数和返回值。使用subscript
关键字,而不是使用func
关键字和函数名称
2.主体部分类似计算属性,带有getter
和setter
基础
对于数组,可以通过下标来获取到数组的元素,如
var arr = [0,1,2,3] arr[1]
同理对于字典也是一样的,只是要通过key来获取键对应的值
除此之外,在Swift中还可以为自己创建的任何类型,如枚举、结构体、类创建下标
如下一个结构体Vector3
,表示三维向量:
struct Vector3{
var x: Double = 0.0
var y: Double = 0.0
var z: Double = 0.0
}
var v = Vector3(x: 1.0,y: 2.0,z: 3.0)
对于结构体,我们可以通过v.x
的形式来获取相应分量的值。但如果想通过v[0]
这种形式来获取分量的值该怎么办呢?
要引入subscript
关键字,可以把subscript
理解为一个特殊的函数,这个函数需要一个参数,并且要有一个返回值。如下,已整型作为参数类型,返回一个浮点型:
subscript(index: Int) -> Double?{
switch index{
case 0: return x
case 1: return y
case 2: return z
default: return nil
}
}
这样实现之后,就可以通过v[0]
来获取分量的值了
在一个枚举、类中可以有多个下标的方法。如下,通过字符串来访问Vector3
的分量的值:
subscript(axis: String) -> Double?{
switch axis{
case "x","X": return x
case "y","Y": return y
case "z","Z": return z
default: return nil
}
}
此时就可以通过v["z"]
来访问z轴分量的值了
现在我们只是通过下标来读取数据,那怎样通过下标来改变数值呢?
计算属性有getter
和setter
,对下标而言也一样,如下:
subscript(index: Int) -> Double?{
get{
switch index{
case 0: return x
case 1: return y
case 2: return z
default: return nil
}
}
set{
guard let newValue = newValue else { return }
switch index{
case 0: x = newValue
case 1: y = newValue
case 2: z = newValue
default: return
}
}
}
这里的newValue
的类型是Double?
(与subscript
的返回值类型是一致的),所以在设置值的时候要解包
这样设置之后,就可以通过v[1] = 100.0
这种形式来设置分量的值了
多维下标
上面讲的都是一个参数的下标,实际上swift语言支持有任意多个参数的下标
如下的一个结构体矩阵Matrix
:
struct Matrix{
var data: [[Double]]
let r:Int
let c:Int
init(row: Int,col: Int) {
self.r = row
self.c = col
data = [[Double]]()
for _ in 0..<r {
let aRow = [Double](repeating: 0.0,count: col)
data.append(aRow)
}
}
}
如下的初始化方法,创建value
都为0.0
的矩阵
var m = Matrix(row: 2,col: 2)
那如何通过下标来访问矩阵中的元素呢?同上面一样,也是使用subscript
。这里有两个参数,返回值为Double
subscript(x:Int,y:Int)->Double{
assert(x>=0&&x<r&&y>=0&&y<c,"Index out of range")
return data[x][y]
}
这里使用了断言,因为数组越界会出错
此时通过m[1,1]
就可以得到矩阵在1,1
,这个位置的元素。注意不是使用m[1][1]
subscript(x:Int,y:Int)->Double{
get{
assert(x>=0&&x<r&&y>=0&&y<c,"Index out of range")
return data[x][y]
}
set{
assert(x>=0&&x<r&&y>=0&&y<c,"Index out of range")
data[x][y] = newValue
}
}
就可以通过m[1,0] = 2.0
来设置值了
但是,通常一般是通过m[1][1]
来获矩阵取值,为支持这种形式,再创建一个subscript
。这个时候只有一个参数,返回值类型为[Double]
:
subscript(row: Int)->[Double]{
get{
assert(row>=0&&row<r,"Index out of range")
return data[row]
}
set(vector){
assert(vector.count == c,"column number does not match")
data[row] = vector
}
}
此时,就可以通过m[1][1]
形式获取值,通过m[0] = [1.5,4.5]
形式设置值了