콘텐츠로 건너뛰기
Home » [Swift] Subscription

[Swift] Subscription

Subscription Syntax

Subscription은 흔히 배열이나 사전에서 인덱스, 키를 사용하여 원소를 뽑아내는 액세스 방법을 말하는데, 일반 타입에서도 subscript 키워드를 사용하여 마치 프로퍼티처럼 사용할 수 있다.

struct TimeTable {
    let multiplier:Int
    subscript (index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimeTable = TimeTable(multiplier: 3)
println("six times three is \(threeTimeTable[6])")

서브스크립션은 함수와 비슷하게 동작하기 때문에 2개 이상의 인덱스를 받을 수 있다.
다음은 내부에 하나의 배열을 프로퍼티로 갖고, 이를 서브스크립션을 사용해 행렬처럼 다루는 구조체의 예이다.

<br />struct Matrix {
    let rows: Int, columns: Int
    var grid: Double[]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(count: rows * columns, repeatedValue: 0.0)
    }
    //
    func indexIsValidRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && columns
    }
    //
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValidRow(row, column: column), "index out of range")
            return grid[(row * column) + column]
        }
         set {
            assert(indexIsValidRow(row, column: column), "index out of range")
            return grid[(row * column) + column0] = newValue
         }
    }
}
var matrix = Matrix(rows:2, columns:2)
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

서브스크립트는 단일 객체 내에서 여러 종류를 만들 수 있다. 다음 예를 보자.

<br />struct TimeTable {
    let time:Int
    var times:Array<String> {
        return ["one":1, "two":2, "three":3, "four":4]
    }
    subscript(index:Int) -> Int {
        return time * index
    }
    subscript(index:String) -> Int? {
        if contains(times.keys, index) {
            return time * times[index]!
        }
        return nil
    }
}

이 예는 글의 서두에 등장한 예제를 확장한 것이다. 입력을 정수가 아닌 문자열로 받아서, 미리 정의된 사전에 대응되는 값으로 변환해주는 것이다. 즉 서브스크립트는 오버로딩가능하다는 이야기이다.
이 코드에 대한 간략한 설명을 첨부한다.

  1. times는 문자열을 정수값을 변환하기 위한 해시테이블이다.
  2. computed property에 대해 구조체에서는 lazy 변경자를 쓸 수 없다.
  3. 문자열을 인덱스로 받는 경우, 사전에 없는 값이 들어오면 nil을 리턴하게 끔 되어 있으므로, 이 리턴타입은 Int? 형이다.
  4. 놀랍게도 사전의 서브스크립션 리턴타입은 옵셔널이다. 사전은 존재하지 않는 키에 대해 쿼리하면 예외를 내는 대신, nil을 리턴한다.