[Swift] 12. subscript

도윤·2021년 7월 24일
0

Swift

목록 보기
14/21

클래스,구조체,열거형에서 해당 타입의 element에 접근하기 위해 사용된다.
수정이나 검색을 하기위한 개별적인 메서드 없이 인덱스를 통해 값을 얻거나 설정할 수 있다. 예를 들어 somArray[index]나 someDictionary[key]로 접근한다.

하나의 타입에 대해 여러개의 subscript를 정의할 수 있고, index value의 타입에 맞게 적절히 선택하게 된다.

Subscript Syntax

instance 이름 뒤에 []를 통해 하나 이상의 데이터에 접근할 수 있다. 이러한 문법은 인스턴스 메서드나 계산 프로퍼티의 문법과 비슷하다. 서브스크립트를 정의하는 방법은 subscript 키워드를 쓰고 하나 이상의 parameter와 return type을 쓰면 된다. instance methods와 달리 subscript는 읽기-쓰기 또는 읽기 전용으로 전달된다.

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

newValue의 타입은 Subscript의 return타입과 동일해야 한다. 계산 프로퍼티처럼 setter의 parameter를 선언하지 않아도 default parameter가 newValue로 설정되어 있다.

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

위의 코드는 read-only subcript이다. 이럴땐 get 키워드를 정의하지 않아도 된다.

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

위의 코드에서 threeTimesTable에 선언된 Subscript는 multiplier에 입력된 정수형 배개변수를 곱해준 값을 반환하는 기능을 가지고 있다.
사용할때 threeTimesTable[6]을 하게 되면 값이 18이 나오게 된다.


Subscript Usage

subscript는 일반적으로 list,sequence와 같은 collection의 element에 접근할 때 간단하게 사용된다.

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

subscript를 활용하여 ["bird",2]의 값을 추가하는 것이다. Dictionary 타입에서는 subscript로 접근한 데이터는 옵셔널타입이다. 따라서 만약 데이터를 삭제하고 싶다면 Nil을 저장하면 삭제가 된다.


Subscript Options

subscript는 여러개의 paramter를 받을 수 있고, 어떠한 타입의 parameter여도 상관이 없으며, 어떠한 타입도 return할 수 있다.

함수에서와 똑같이 서브스크립트는 매개변수들에 default값을 줄 수도 있고 Variadic 매개변수를 줄 수도 있다. 하지만 in-out 매개변수는 서브스크립트에서 사용할 수 없다.

클래스와 구조체에서 필요한 만큼 subcript를 만들 수 있다. 여러개가 선언되어 있을 때 매개변수로 주어진 값들의 타입을 보고 어떤 서브스크립트인지 추론하게 되는데 이렇게 여러개의 서브스크립트의 정의는 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
        }
    }
}

subscript로 정의한 부분을 보면 row,col 두개의 매개변수가 선언되어 있음을 확인 할 수 있다.

var matrix = Matrix(rows: 2, columns: 2)

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


Type subscripts

서브 스크립트도 타입 자체로 접근할 수 있는 타입 서브 스크립ㅌ트가 존재한다. subscript 키워드 전 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)

0개의 댓글