Swift

subscript

Phililip
728x90

안녕하세요.

 

이번에는 Swift의 subscript에 대해 알아볼게요.

 


 

클래서, 구조체, 열거형에서 subscript 정의가 가능합니다.

 

그럼 subscript란 무엇이냐?

 

subscript를 사용하면 collection, list, sequence의 element에 쉽게 접근할 수 있어요.

(Array의 someArray[index] 또는 Dictionary의 someDictionary[key] 처럼 말이죠!)

 

 

또한 하나의 타입에 여러 개의 subscript를 구현할 수 있고, overload도 가능해요.

 

 

 

## 1. Subscript Syntax

subscript 키워드를 사용해서 subscript를 정의할 수 있어요.

 

subscript는 read-write 또는 read-only로만 구현이 가능합니다.

 

아래처럼 getter, setter를 구현하면 read-write 인 것이고,

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

 

 

아래처럼 setter를 생략하면 read-only인 것이에요ㅎㅎ

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

또는

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

 

 

subscript를 구현했으면 사용방법도 알아야겠죠?

 

Array나 Dictionary처럼 인스턴스 이름 뒤에 value를 대괄호([])로 감싸주면 element에 접근이 가능해요.

 

 

즉, 아래처럼 사용할 수 있는 것이죠.

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")  // "six times three is 18"
threeTimesTable[6] = 10				❎  // Cannot assign through subscript: subscript is get-only

 

마지막 줄을 보면 subscript가 read-only로 구현되어 있기 때문에, 값을 대입하려고 하니까 에러가 났습니다.

 

 

 

## 2. 여러 개의 SubScript 

subscript는 여러 개를 구현할 수 있어요.

 

또한, subscript에 필요한 input parameter의 수도 제한이 없습니다.

 

 

예를 들어볼게요.

 

아래처럼 Matrix라는 구조체를 만들었다고 해볼게요.

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

 

 

1차원 배열인 grid의 element에 쉽게 접근하도록 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)
    }
    
    subscript(index: Int) -> Double {	✅
        get {
            return grid[index]
        }
        set {
            grid[index] = newValue
        }
    }
}

matrix[3] = 2.0		// Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 0.0, 2.0])

 

 

 

그런데, 1차원인 grid를 아래같이 2차원 배열처럼 쓰고 싶을 수가 있겠죠?

출처 : https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html

 

 

 

이럴 때, row와 column을 input parameter로 받는 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)
    }
   
    subscript(index: Int) -> Double {
        get {
            return grid[index]
        }
        set {
            grid[index] = newValue
        }
    }

    subscript(row: Int, column: Int) -> Double {	✅
        get {
            return grid[(row * columns) + column]
        }
        set {
            grid[(row * columns) + column] = newValue
        }
    }
}

matrix[0, 1] = 1.5		// Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 0.0, 0.0])

 

 

 

## 3. Type Subscript

위에서 설명한 subscript는 정확하게 말하면 Instance Subscript라고 해요.

(특정 타입의 인스턴스에서 호출할 수 있는 subscript라는 의미죠.)

 

그런데, 특정 타입 그 자체에서 subscript도 호출할 수 있어요. 그것을 Type Subscript라고 부릅니다.

 

Type Subscript를 구현하려면, subscript 키워드 앞에 static 키워드를 붙여주면 됩니다.

(클래스에서 구현한다면 class 키워드를 대신 사용해도 괜찮아요.)

 

 

Type Subscript 예를 들어볼게요.

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)		// mars

 

static + subscript 키워드를 사용해서 Type Subscript를 구현했기 때문에, Planet이란 enum 타입에 대괄호를 사용해서 element에 접근할 수 있게 됩니다ㅎㅎ

 

 

 

 

## 참고

- https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html

 

Subscripts — The Swift Programming Language (Swift 5.6)

Subscripts Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for se

docs.swift.org

 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'Swift' 카테고리의 다른 글

클로저에서 [weak self] 사용할 때 주의할 점  (0) 2022.04.16
Automatic Reference Counting (ARC)  (0) 2022.04.10
Struct와 Class  (0) 2022.04.02
FormatStyle  (0) 2022.03.24
PersonNameComponents를 사용해서 이름 파싱하기  (0) 2022.03.23