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