下标(subscript)
使用subscript可以给任意类型(枚举、结构体、类)增加下标功能,有些地方也翻译为:下标脚本
subscript的语法类似于实例方法、计算属性,本质就是方法(函数)
class Point {var x: Double = 0var y: Double = 0subscript(index: Int) -> Double {set {if index == 0 {x = newValue} else if index == 1 {y = newValue}}get {if index == 0 {return x} else if index == 1 {return y}return 0}}}let point = Point()point[0] = 1point[1] = 2let x = point[0]let y = point[1]print(x, y) // 1.0 2.0
给point添加下标,point[0]就是给x赋值,point[1]就是给y赋值。
subscript中定义的返回值类型决定了:
- get方法的返回值类型
- set方法中的newValue的类型
下标的细节
1、subscript可以没有set方法,但必须要有get方法
class Point {var x: Double = 0var y: Double = 0subscript(index: Int) -> Double {get {if index == 0 {return x} else if index == 1 {return y}return 0}}}
2、如果只有get方法,可以省略get
class Point {var x: Double = 0var y: Double = 0subscript(index: Int) -> Double {if index == 0 {return x} else if index == 1 {return y}return 0}}
3、可以设置参数标签
class Point {var x: Double = 0var y: Double = 0subscript(index i: Int) -> Double {if i == 0 {return x} else if i == 1 {return y}return 0}}var p = Point()print(p[index: 0], p[index: 1]) // 0.0 0.0
添加参数标签后,使用下标时,需要书写参数标签。
4、下标可以是类型方法
class Sum {static subscript(v1: Int, v2: Int) -> Int {v1 + v2}}print(Sum[10, 20]) // 30
结构体、类作为返回值对比
struct Point {var x = 1, y = 2}class PointManager {var point = Point()subscript(index: Int) -> Point {set { point = newValue}get { point }}}var pm = PointManager()pm[0].x = 10pm[0].y = 20print(pm[0].x, pm[0].y) // 10 20
pm[0].x = 10这行代码,在外部传入的时int类型的数据,但是set方法里接收的是point类型,原因是pm[0].x = 10相当于:
pm[0] = Point(x: 10, y: pm[0].y)
如果Point是类,可以省略下标中的get方法:
class Point {var x = 1, y = 2}class PointManager {var point = Point()subscript(index: Int) -> Point {get { point }}}var pm = PointManager()pm[0].x = 10pm[0].y = 20print(pm[0].x, pm[0].y)
原因是类是引用类型,get方法返回的是指针,所以可以直接修改对应的x和y的值。
接收多个参数的下标
class Grid {var data = [[0, 1, 2],[3, 4, 5],[6, 7, 8]]subscript(row: Int, column: Int) -> Int {set {guard row >= 0 && row <= 3 && column >= 0 && column <= 3 else {return}data[row][column] = newValue}get {guard row >= 0 && row <= 3 && column >= 0 && column <= 3 else {return 0}return data[row][column]}}}var grid = Grid()grid[0, 1] = 111grid[1, 0] = 222grid[2, 2] = 333print(grid.data)
打印结果:
[[0, 111, 2], [222, 4, 5], [6, 7, 333]]
