[Swift5] Subscripts

Junyoung Park·2022년 3월 18일
0

Swift5 Docs

목록 보기
26/37
post-thumbnail
  • 다음은 Swift 5.6 Doc의 Subscript 공부 내용을 정리했음을 밝힙니다.

Subscripts

클래스, 구조체, 열거형에서 서브스크립트를 통해 원소에 쉽게 접근할 수 있다. 게터나 세터 등 메소드를 사용하지 않고 서브스크립트를 통해 직접 접근 가능.

서브스크립트 문법

인스턴트 이름 뒤[] 안에 쓴 인덱스 값으로 컬렉션 내부에 접근할 수 있다. 게터와 세터 메소드를 통해 인스턴스 값을 조회하거나 수정할 수 있었는데, 서브스크립트 또한 그렇다.

subscript(index: Int) -> Int {
    get {
        // Return an appropriate subscript value here.
    }
    set(newValue) {
        // Perform a suitable setting action here.
    }
}

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

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 메소드를 직접 구조체 내부에 커스텀할 수 있다. TimesTable 구조체를 정의할 때 넘겨준 multiplier 저장 프로퍼티와 서브스크립트를 사용할 때 넘겨준 파라미터 값을 곱한 게 결과다.

서브스크립트 사용

서브스크립트는 빠르게 값을 조회하거나 수정할 수 있다.

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

numberOfLegs 딕셔너리를 선언한 뒤 딕셔너리에 키로 등록된 값을 통해 값을 조회할 수 있다. 키가 없는 데 새로운 키를 만들어 값을 추가할 수도 있다. 그런데 값이 없는 키를 서브스크립트를 통해 조회할 수도 있다. 그렇기 때문에 딕셔너리 키-값 서브스크립트는 옵셔널 값을 리턴한다.

서브스크립트 옵션

서브스크립트는 입력값으로 어떤 타입이든 여러 개 받을 수 있고, 어떤 타입 역시 리턴할 수 있다. 이는 함수와 비슷한데, 디폴트 값을 설정할 수도 있다. 하지만 인-아웃 파라미터는 설정할 수 없다.

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

let someValue = matrix[2, 2]
// This triggers an assert, because [2, 2] is outside of the matrix bounds.

행렬 구조체는 행과 열로 구성되어 있다. 인덱스를 통해 값을 조회하고 수정할 수 있다. indexIsValid로 현재 행렬 인스턴스의 범위를 확인할 수 있다. 서브스크립트를 통해 게터와 세터가 커스텀된다는 데 주의.

이니셜라이저로 행과 열을 파라미터로 입력받고, 이를 사용해 배열을 만들어 차례대로 담아둔다. 일차원 배열을 이차원 배열로 사용하기 위해 행과 열을 계산해 조회 및 수정한다.

matrix 인스턴스의 (0, 1), (1, 0)에 서브스크립트 문법을 통해 직접 값을 줄 수 있다. 물론 서브스크립트로 넘겨주는 각 행과 열이 구조체 내 정의된 indexIsValid로 유효한지 확인되어야 한다.

타입 서브스크립트

인스턴스 서브스크립트가 있다면 타입 그 자체에 적용 가능한 서브스크립트 문법도 있다. 타입 프로퍼티 등과 마찬가지로 static 키워드나 (클래스에 있어서는 오버라이드할 수 있도록) 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)

인스턴스를 만들지 않아도 사용 가능하며, 모든 인스턴스가 공통적으로 가져야 할 값이라면 타입 서브스크립트로 값을 세팅하거나 가져오는 게 효율적.

profile
JUST DO IT

0개의 댓글