类,结构体和枚举都可以用来定义下标,下标(subscripts
)是用来读取集合(collectrion
),列表(list
)或序列(sequence
)中的成员元素(member elements)的一种快捷方式。我们可以使用下标来设置和检索集合列表和序列中元素的值,而并非需要其他单独的方法来设置和检索元素的,举个例子在Array的实例中以索引位置index的方式来读取array里的元素可以写为 someArray[index]
,字典里则可以写为 someDictionary[key]
下标允许我们在实例名称后的方括号里面写一个或多个值的方法来查询某个类型的实例。下标语法与实例方法和计算型属性语法的写法比较相似。用subscript
关键字引出并介绍下标语法的定义,可以像实例方法那样用来指定一个或多个输入参数和一个返回值,和实例方法不同的是,下标只是用来读写(read-write
)和只读(read-only
)操作的。下标语法中的setter和getter与计算型属性中的getter和setter用法是一样的。
// 下标语法的常规表达形式
subscript(index: Int) -> Int {
get {
}
// 和计算型属性里set的规则是一样的
set(newValue) {
}
}
下面的这个例子是一个只读型下标的实现,定义的结构体乘法表(TimesTable)用来展示整数的乘法表。
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// 输出:six times three is 18
结构体TimesTable中的实例let threeTimesTable = TimesTable(multiplier: 3)
是用来表达一个某个整数乘以3的3乘乘法表(threeTimesTable)实例。threeTimesTable[6]表示在3乘乘法表位置第6个数。所以该实例和输出就是 6乘以3(3乘6)的表达,而不是3乘以6
下标的确切含义取决于使用场景。下标通常作为访问集合,列表或序列中元素的快捷方式。你可以针对自己特定的类或结构体的功能来自由地以最恰当的方式实现下标。
举个例子哦,Swift 的 Dictionary 类型实现下标用于对其实例中储存的值进行存取操作。为字典设值时,在下标中使用和字典的键类型相同的键,并把一个和字典的值类型相同的值赋给这个下标。
// 定义该字典
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
// 在原有的字典中添加一个新元素
numberOfLegs["bird"] = 2
上面这个例子定义了一个变量叫numberOfLegs
它是一个字典类型的变量值,三对key-value组分别代表了三个不同组别的动物,而这个类型字典会被swift类型推断为[String: Int]
创建完这个字典后,三个值key是spider value是8,key是ant value是6,key是cat value是4,
下标可以接受任何输入型的参数,并且这些参数可以是任何类型的参数,下标参数也可以返回任何类型的参数,下标可以像函数那样接受一个变量参数作为默认值来作为输入型参数,和函数不同的是下标不能使用输入输出型参数(In-out parameter)作为输入参数,类型和结构体可以提供很多个下标,类或结构体的定义里面有多个下标,这样的下标叫做下标的重载(subscript overloading
)。
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
// **
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
// **
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
var matrix = Matrix(rows: 2, columns: 2)
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
let someValue = matrix[2, 2]
上面的是实例下标(instance subscripts
)在上面已经介绍过了,实例下标是一个可以调用在某个特定类型的实例上的下标,我们也可以定义一个调用在类型本身上的下下标,这样的下标我们称之为类型下标(type subscript
)。可以用static
关键字在subscript前面介绍并引出该类型下标(结构体和枚举),而类的类型下标要用class
代替,从而来允许子类重写父类下标的实现。下面这个例子展示了怎么定义和调用这个类型下标。
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
static subscript(n: Int) -> Planet {
return Planet(rawValue: n)!
}
}
let mars = Planet[4]
print(mars)