Subscripts : collection/list/sequence 의 요소에 접근하기 위한 shortcut.

하나의 type 에 여러 subscript 를 정의할 수 있고, subscript 에 전달하는 index 의 type 에 따라 적절한 subscript 를 선택할 수 있음. Subscript 는 일차원에 한정되어 있지 않고, 여러 input parameter 를 넣을 수 있는 subscript 를 정의할 수 있음

Subscript Syntax

Subscript 는 instance 이름 뒤의 대괄호 [] 에 하나 이상의 값을 써서 instance 에 query 를 할 수 있게 해줌.

subscript 키워드를 써서 subscript 정의를 작성. Subscript 를 작성하는 문법은 method, computed property 문법과 비슷함. Instance 메서드와는 다르게 subscript 는 read-write 거나 read-only 임.

subscript(index: Int) -> Int {
    get {
        // Return an appropriate subscript value here.
    }
    // 만약 setter 에 parameter 를 전달하지 않는다면 newValue 라는 기본 이름이 사용됨
    set(newValue) {
        // Perform a suitable setting action here.
    }
}

// read-only subscript
subscript(index: Int) -> Int {
    // Return an appropriate subscript value here.
}

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Prints "six times three is 18".

Subscript Usage

Subscript 는 사용되는 문맥에 따라 달라짐. 주로 collection/list/sequence 에 있는 요소들을 접근하기 위한 shortcut 으로 사용됨.

e.g. Dictionary type 은 instance 에 저장된 값을 가져오고 설정하기 위한 subscript 를 구현함

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2

Subscript Options

Subscript 는 여러 개의 input parameter 를 받을 수 있고, parameter 들은 어떤 타입이든 될 수 있으며 subscript 가 return 하는 타입은 어떤 타입이든 가능함.

Subscript 는 variadic parameter, default value 를 parameter 가 가질 수 있지만 in-out parameter 는 가질 수 없음.

Class, struct 는 가능한 한 많은 subscript 을 구현할 수 있고, 가장 적절한 subscript 는 subscript 괄호 안에 사용된 값의 타입이나 그 값에 의해 추론됨

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
        }
    }
}

matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

Type Subscripts

Type 자체에 호출할 수 있는 subscript 를 정의할 수도 있음.

subscript 키워드 전에 static 키워드를 써서 type subscript 를 작성함. Class 는 class 키워드를 써서 subclass 가 해당 subscript 의 구현을 override 할 수 있게 함

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)