Swift Subscripts
Subscripts can be defined in classes, structures, and enumerations. They are considered a shortcut for accessing elements in an object, collection, or sequence without needing to call specific instance assignment and access methods.
For example, you can access an element in an array instance like this: someArray[index]
, and an element in a dictionary instance like this: someDictionary[key]
.
Multiple subscripts can be defined for the same target, overloaded by the type of the index value, and the number of index values can be multiple.
Subscript Syntax and Usage
Syntax
Subscripts allow you to access and assign values to an instance by passing one or more index values in brackets following the instance.
The syntax is a mix of instance methods and computed properties.
Similar to defining instance methods, subscripts are defined using the subscript
keyword, explicitly declaring one or more parameters and a return type.
Unlike instance methods, subscripts can be read-write or read-only, similar to computed properties' getter and setter:
subscript(index: Int) -> Int {
get {
// Declare the value for the subscript
}
set(newValue) {
// Perform the assignment operation
}
}
Example 1
import Cocoa
struct Subexample {
let decrementer: Int
subscript(index: Int) -> Int {
return decrementer / index
}
}
let division = Subexample(decrementer: 100)
print("100 divided by 9 equals \(division[9])")
print("100 divided by 2 equals \(division[2])")
print("100 divided by 3 equals \(division[3])")
print("100 divided by 5 equals \(division[5])")
print("100 divided by 7 equals \(division[7])")
The output of the above program is:
100 divided by 9 equals 11
100 divided by 2 equals 50
100 divided by 3 equals 33
100 divided by 5 equals 20
100 divided by 7 equals 14
In the example above, a division operation instance is created using the Subexample
structure. The value 100 is passed as a parameter to the structure's constructor to initialize the instance member decrementer
.
You can get the result using the subscript, for example, division[2]
is 100 divided by 2.
Example 2
import Cocoa
class DaysOfWeek {
private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"]
subscript(index: Int) -> String {
get {
return days[index] // Declare the value for the subscript
}
set(newValue) {
self.days[index] = newValue // Perform the assignment operation
}
}
}
var p = DaysOfWeek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])
The output of the above program is:
Sunday
Monday
Tuesday
Wednesday
Usage
Subscripts have different meanings depending on the context of their use.
They are commonly used as a shortcut for accessing elements in collections, lists, or sequences.
You can freely implement subscripts in your specific classes or structures to provide appropriate functionality.
For example, Swift's Dictionary implements subscripts to store and retrieve values in its instances. You use a value of the same type as the dictionary's index, and assign a value of the dictionary's value type to the subscript to set a new value:
import Cocoa
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
print(numberOfLegs)
The output of the above program is:
["ant": 6, "bird": 2, "cat": 4, "spider": 8]
The above example defines a variable named numberOfLegs
and initializes it with a dictionary literal containing three key-value pairs. The type of numberOfLegs
is inferred to be a Dictionary
.
Subscript Options
Subscripts allow for an arbitrary number of input parameters, and there are no restrictions on the types of these parameters.
The return value of a subscript can be of any type.
Subscripts can use variable parameters and variadic parameters.
A class or structure can provide multiple subscript implementations based on its needs. These implementations are differentiated by the types of the parameters passed in the subscript definition. When using the subscript, the appropriate implementation is automatically matched and executed, which is known as subscript overloading.
import Cocoa
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)
}
subscript(row: Int, column: Int) -> Double {
get {
return grid[(row * columns) + column]
}
set {
grid[(row * columns) + column] = newValue
}
}
}
// Create a new 3x3 Matrix instance
var mat = Matrix(rows: 3, columns: 3)
// Set values using subscript
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
// Get values using subscript
print("\(mat[0,0])")
print("\(mat[0,1])")
print("\(mat[1,0])")
print("\(mat[1,1])")
The output of the above program is:
1.0
2.0
3.0
5.0
The Matrix
structure provides a constructor method with two parameters, rows
and columns
, creating an array of type Double
large enough to accommodate rows * columns
elements. The array is initialized with a size and each element set to 0.0
.
You can construct a new Matrix
instance by passing the appropriate number of rows
and columns
.