5月27日 11:27
Swift 下标 subscript 怎么自定义?和多参数下标
下标(subscript)让你用 instance[index] 的方式访问值,不需要调方法。Array、Dictionary 的 [] 访问就是下标实现的。自定义类型也可以定义下标,用 subscript 关键字。
下标本质是 getter + setter 的语法糖,和计算属性类似——可以只读也可以读写,可以有多个参数。区别是下标用 [] 调用,属性用 . 调用;下标可以接受参数,属性不能。
追问
下标可以接受多个参数吗?
可以,参数数量和类型没有限制。典型用法是二维数组用 matrix[row, col] 访问。也可以用不同类型的参数重载下标——比如字典同时支持 dict["key"] 和 dict[0]。参数还可以有默认值和可变参数。
下标和方法的区别?什么时候该用下标?
下标是访问语义——"取一个值"或"设一个值"。方法是操作语义——"执行一个动作"。如果一个操作的核心含义是"按索引取值",用下标;如果是"做某件事",用方法。字典的 dict["key"] 是下标(取值),dict.removeValue(forKey:) 是方法(执行删除)。别滥用下标——复杂逻辑用方法更清晰。
类型下标是什么?
用 static subscript 定义,通过类型名直接调用:SomeType[index],不需要实例。枚举常用类型下标——比如 Planet[4] 返回第四颗行星。类型下标不能是实例下标的重载(参数签名相同时会冲突)。
下标能抛出错误吗?
能。Swift 5.2 开始下标可以标记 throws,调用时需要 try。不过实际项目中很少用——下标调用期望是简单的取值操作,抛出错误会让调用方写一堆 try-catch,违背了下标的简洁语义。索引越界通常用返回 Optional(dict[key] 返回 Value?)或直接 crash(array[index])来处理,而不是抛错误。
写段代码
swiftstruct Matrix { let rows: Int, cols: Int var grid: [Double] init(rows: Int, cols: Int) { self.rows = rows; self.cols = cols self.grid = Array(repeating: 0.0, count: rows * cols) } subscript(row: Int, col: Int) -> Double { get { grid[row * cols + col] } set { grid[row * cols + col] = newValue } } } var m = Matrix(rows: 3, cols: 3) m[0, 0] = 1.0 m[1, 1] = 2.0 print(m[0, 0]) // 1.0 // 类型下标 enum Planet: Int { case mercury = 1, venus, earth, mars static subscript(n: Int) -> Planet? { Planet(rawValue: n) } } print(Planet[3]!) // earth