Swift/Swift 가이드

[Swift] 공식 문서 - Subscripts

유정주 2022. 7. 24. 16:37
반응형

* 완벽한 번역이 아닌 내용을 한 줄 한 줄 읽는 것에 의의를 두었습니다.

* 파파고의 힘을 빌려 번역했으며 잘못된 번역이 있다면 댓글로 알려주세요.

 

새로 배운 점

  • 클래스, 구조체, 열거형은 서브스크립트(subscripts)를 정의할 수 있다.
  • 서브 스크립트를 사용하면 다른 메서드 없이 인덱스를 사용하여 값을 설정하고 검색할 수 있다.
  • subscript 키워드로만 서브스크립트를 정의 가능하다.
  • 클래스와 구조체는 필요한 만큼의 서브스크립트를 구현할 수 있다.
  • 여러 개의 서브스크립트를 정의하는 것을 subscript overloading이라고 한다.
  • 사용자 타입에 맞춰 여러 개의 파라미터를 받는 서브스크립트를 정의할 수도 있다.

 

서론

클래스, 구조체, 열거형은 서브스크립트(subscripts)를 정의할 수 있습니다.

서브스크립트는 콜렉션, 리스트, 시퀀스의 멤버 변수에 접근하는 단축어로 사용됩니다.

서브스크립트를 사용하면 다른 메서드 없이 인덱스를 사용하여 값을 설정하고 검색할 수 있습니다.

예를 들어, 배열 인스턴스의 요소는 someArray[index]로 접근할 수 있고,

딕셔너리의 요소는 someDictionary[key]로 접근할 수 있습니다.

 

단일 타입에 대해 여러 서브스크립트를 정의할 수 있고,

서브스크립트에 전달되는 인덱스 값의 타입에 따라서 적절한 서브스크립트 오버로드가 사용됩니다.

서브스크립트는 사용자 정의 타입에 따라 여러 입력 파라미터를 사용하여 정의할 수도 있습니다.

 

Subscript Syntax

서브스크립트는 인스턴스 메서드나 연산 프로퍼티 문법과 유사합니다.

서브스크립트의 정의는 subscript 키워드로만 가능하고 하나 이상의 매개변수와 반환 값을 지정합니다.

매개변수나 반환형을 생략할 수 없고, getter와 setter 모두 구현, get-only 구현은 가능하지만 set-only는 불가합니다.

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

newValue는 서브스크립트의 리턴 값과 동일하며 생략 가능합니다.

 

get-only는 getter와 마찬가지로 get의 중괄호를 제거하여 작성할 수 있습니다.

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

 

아래는 get-only(read-only)로 작성한 서브스크립트가 있는 TimesTable 구조체입니다.

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"

이 예제에서 TimesTable 인스턴스는 multiplier로 3을 전달합니다.

threeTimesTable[6]으로 서브스크립트를 호출하여 6 * 3인 18을 반환합니다.

 

Subscript Usage

subscript는 일반적으로 콜렉션, 리스트, 시퀀스에서 멤버 요소에 접근하기 위한 용도로 사용되었습니다.

하지만 특정 클래스가 구조체의 기능을 위해 서브스크립트를 구현할 수 있습니다.

 

예를 들어, 스위프트의 Dictionary 타입은 서브스크립트를 딕셔너리 인스턴스에서 저장되어 있는 값을 설정하거나 탐색하도록 구현합니다.

딕셔너리에서 서브스크립트 대괄호 안에 딕셔너리 키 타입의 키를 전달하고 딕셔너리 value 타입의 값을 할당하여 값을 설정합니다.

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

 

이 예제는 서브스크립트 할당을 사용하여 "bird"라는 String 키를 추가하고 2라는 Int 값을 할당합니다.

 

Subscript Options

서브스크립트는 여러 개의 input 파라미터를 취할 수 있고, 이 파라미터는 어떠한 타입이든지 상관 없습니다.

서브스크립트는 어떤 타입의 값도 반환할 수 있습니다.

하지만 in-out 파라미터는 사용할 수 없습니다.

 

클래스와 구조체는 필요한 만큼의 서브스크립트를 구현할 수 있습니다.

구현된 서브스크립트들은 서브스크립트가 사용되는 순간에 대괄호 내의 값이나 타입에 기반하여

적절한 서브스크립트가 선택되어 수행됩니다.

이렇게 여러 개의 서브스크립트를 정의하는 것을 subscript overloading이라고 합니다.

 

대부분은 하나의 파라미터만 쓰지만,

사용자 타입에 맞춰 여러 개의 파라미터를 받는 서브스크립트를 정의할 수도 있습니다.

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

적절한 row와 column 값을 전달하여 아래처럼 새로운 Matrix 인스턴스를 생성할 수 있습니다.

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

 

위 예시는 아래 그림같은 행렬을 생성합니다.

 

행렬의 값은 서브스크립트에 row와 column 값을 전달하여 설정할 수 있습니다.

row와 column 값은 코마로 분리됩니다.

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

위 코드 이후 아래 그림처럼 행렬이 설정됩니다.

 

Matrix 구조체의 서브스크립트의 getter/setter는 둘 다 row와 column 값이 유효한지 체크하는 assertion이 있습니다.

전달된 row와 column 값이 행렬 경계를 벗어나지 않는지 확인합니다.

 

만약 행렬 범위를 넘어서면 assertion이 트리거됩니다.

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

 

Type Subscripts

인스턴스 서브스크립트는 특정 타입의 인스턴스에서 호출할 수 있습니다.

타입 자체에서 호출할 수 있는 서브스크립트도 정의할 수 있습니다.

이를 타입 서브스크립트(type subscript)라고 합니다.

타입 서브스크립트는 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)

 

 

 

참고

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

반응형