[최종 수정일 : 2018.08.29]
원문 : 애플 개발 문서 Swift 4.2 Language Guide - Subscripts
서브스크립트(Subscripts)
클래스, 구조체, 열거형은 컬렉션(collection), 리스트(list), 시퀀스(sequence)의 멤버요소에 간단하게(shortcuts) 접근하는 서브스크립트(subscripts)를 정의할수 있습니다. 설정하거나 가져오는 별개의 메소드 없이 인덱스(index)로 값을 설정하거나 가져오기 위해 서브스크립트를 사용합니다. 예를들어, someArray[index]
와 같은 Array
인스턴스에 있는 요소들과 someDictionary[key]
와 같은 Dictionary
인스턴스에 있는 요소들에 접근합니다.
단일 타입에 대해 여러개의 서브스크립트를 정의할 수 있고, 서브스크립테에 전달하는 인덱스의 타입에 따라 적절한 서브스크립트가 오버로드(overload)하여 선택됩니다. 서브스크립트(Subscripts)는 단일 차원(dimension)으로 제한되지 않고, 사용자정의 타입의 요구사항에 따라 여러개의 입력 매개변수로 서브스크립트를 정의 할수 있습니다.
서브스크립트 문법(Subscript Syntax)
서브스크립트는 인스턴스 이름 뒤에 대괄호(square brackets []
) 하나 이상의 값들을 작성해서, 타입의 인스턴스를 조회하는 것이 가능합니다. 이러한 문법은 인스턴스 메소드 문법과 계산 프로퍼티 문법과 비슷합니다. subscript
키워드를 작성하여 서브스크립트를 정의하고, 하나 이상의 입력 매개변수와 반환 타입을 지정합니다. 인스턴스 메소드와 다르게, 서브스크립트는 읽기-쓰기(read-write) 또는 읽기 전용(read-only)이 가능합니다. 이 동작은 계산 프로퍼티와 같은 방법으로 getter와 setter를 이용하게 됩니다.
subscript(index: Int) -> Int {
get {
// return an appropriate subscript value here
}
set(newValue) {
// perform a suitable setting action here
}
}
newValue
의 타입은 서브스크립트의 반환 타입과 같습니다. 계산 프로퍼티 처럼, setter의 (newValue)
매개변수를 지정하지 않도록 선택할수 있습니다. 여러분이 직접 제공하지 않은 경우에, setter에 기본 매개변수 newValue
가 제공됩니다.
읽기전용(read-only) 계산 프로퍼티처럼, get
키워드와 중괄호를 제거해서, 읽기전용(read-only) 서브스크립트 선언을 단순하게 할 수 있습니다.
subscript(index: Int) -> Int {
// return an appropriate subscript value here
}
다음 예제는 정수형 n단(n-times-table)을 표현하기 위해 TimesTable
구조체를 정의한 읽기전용(read-only) 서브스크립트를 구현한 것입니다.
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
의 새로운 인스턴스는 3단(three-times-table)을 표현하기 위해 생성됩니다.이것은 인스턴스의 multiplier
매개변수에 사용하는 값으로 구조체의 초기화(initializer)
에 값 3
을 전달하는 것을 나타냅니다.
threeTimesTable[6]
를 호출에서 볼수 있는 것처럼, 서브스크립트를 호출해서 threeTimesTable
인스턴스를 조회할수 있습니다. 이것은 값 18
을 반환하는 3단(three-times-table)에서 6번째 항목을 요청합니다.
주의
n단(n-times-talbe)은 고정된 수학공식을 기반으로 합니다.threeTimesTable[someIndex]
에 새로운 값을 설정하는 것은 적절하지 않고,TimeTable
에 대한 서브스크립트는 읽기전용(read-only) 서브스크립트로 정의됩니다.
서브스크립트 사용법(Subscript Usage)
서브스크립트(subscript)
의 정확한 의미는 사용되는 컨텍스트(context)에 따라 결정됩니다. 서브스크립트는 일반적으로 컬렉션, 리스트, 시퀀스 에서 멤버 요소들에 접근하는 쉬운방법(shortcut)으로 사용됩니다. 특정 클래스나 구조체의 기능과 가장 잘 어울리는 방법으로 서브스크립트를 자유롭게 구현합니다.
예를들어, Swift의 Dictionary
타입은 Dictionary
인스턴스에 있는 저장소에 값을 설정하고 가져오기 위해 서브스크립트를 구현합니다. 서브스크립트 대괄호(brackets []
) 안에 딕셔너리의 키 타입의 키(key)를 딕셔너리에 값을 설정 할 수 있고, 서브스크립트에 딕셔너리의 값 타입의 값을 할당 할 수 있습니다.
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
위의 예제는 numberOfLegs
변수를 정의하고 3개의 key-value 쌍을 포함한 리터럴(literal) 딕셔너리로 초기화 하였습니다. numberOfLegs
딕셔너리의 타입은 [String: Int]
로 추론됩니다. 딕셔너리를 생성하고 난 후에, 이 예제는 딕셔너리에 "bird"
라는 String
키와 Int
인 2
의 값을 추가하기 위해 서브스크립트 할당을 사용합니다.
Dictionary
서브스크립트에 대한 자세한 정보는 딕셔너리 사용과 수정하기(Accessing and Modifying a Dictionary)를 보세요.
주의
Swift의Dictionary
타입 구현은 서브스크립트로 가져오고 옵셔널(optional) 타입을 반환하는 key-value 서브스크립트입니다. 위의numberOfLegs
딕셔너리에 대해, key-value 서브스크립트는Int?
또는"옵셔널(optional) int"
타입을 가져오고 반환합니다.Dictionary
타입은 모든 키가 값을 가져오지는 않을 것이라는 것을 모델링하고, 키에 대한 값을 제거하는 방법으로는 키에nil
을 할당하기 위해, 옵셔널 서브스크립트 타입을 사용합니다.
서브스크립트 옵션(Subscript Options)
서브스크립트는 임의의 입력 매개변수의 개수를 가질수 있고, 이러한 입력 매개변수는 어떤 타입도 될수 있습니다. 서브스크립트는 어떤 타입이든 반환할수 있습니다. 서브스크립트는 가변 매개변수를 사용할수 있지만, in-out 매개변수를 사용하거나 기본 매개변수 값을 제공할 수는 없습니다.
클래스나 구조체는 필요한 경우에 많은 서브스크립트 구현을 제공할 수 있고, 값의 타입이나 서브스크립트가 사용되는 시점에 서브스크립트 대괄호 포함된 값들을 기반으로 추론되어 적절한 서브스크립트가 사용될 것입니다. 여러개의 서브스크립트를 정의하는 것을 서브스크립트 오버로딩(subscript overloading)이라고 합니다.
서브스크립트에 단일 매개변수를 가져오는 것이 가장 일반적이지만, 타입에 맞게 여러개의 매개변수로 서브스크립트를 정의할 수 있습니다. 다음 예제는 Double
값의 2차원 행렬(two-dimensional matrix)을 표현하는 Matrix
구조체를 정의한 것입니다. Matrix
구조체의 서브스크립트는 2개의 정수 매개변수를 가져옵니다.
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
}
}
}
Matrix
는 2개의 매개변수 rows
와 columns
를 받는 초기화를 제공하고, Double
타입의 rows * columns
값을 저장할 수 있는 크기의 배열을 생성합니다. 행렬에서 각 위치에 초기값 0.0
을 넣습니다. 이를 위해, 정확한 크키의 새로운 배열을 생성하고 초기값을 생성하기 위해, 배열의 크기와 초기값 0.0
을 배열의 초기화에 전달합니다. 이 초기화는 기본 값으로 배열 생성하기(Creating an Array with a Default Value)에서 더 자세히 설명되어 있습니다.
초기화에 적절한 행과 열 갯수를 전달해서, 새로운 Matrix
인스턴스를 구성할 수 있습니다.
var matrix = Matrix(rows: 2, columns: 2)
위의 예제에서, 2개의 행(rows)과 2개의 열(columns)로 새로운 Matrix
인스턴스를 생성하였습니다. Matrix
인스턴스에 대한 grid
배열은 왼족 위에서 오른족 아래로 읽는 것과 같이, 행렬을 실제로 평면화시킨 버젼입니다.
행렬에서의 값은 서브스크립트에 행과 열 값을 콤마(,
)로 구분하여 전달해서 설정할 수 있습니다.
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
이러한 두개의 문장은 행력의 오른쪽 위쪽(row
가 0
이고 column
이 1
) 위치에 1.5
값을 설정하고, 왼족 아래(row
가 1
이고 column
이 0
) 위치에 3.2
값을 설정하기 위해, 서브스크립트의 setter를 호출합니다.
Matrix
서브스크립트의 getter와 setter 모두 서브스크립트의 row
와 column
값이 유효한지 assertion을 확인합니다. 이 assertion을 지원하기 위해, Matrix
는 요청된 row
와 column
가 행력의 범위 안에 있는지 확인하기 위해, 편리한 메소드 indexIsValid(row:column:)
을 가지고 있습니다.
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
행별 범위를 벗어나느 서브스크립트에 접근하려고 하면 assertion이 발생됩니다.
let someValue = matrix[2, 2]
// this triggers an assert, because [2, 2] is outside of the matrix bounds
'Swift > Language Guide' 카테고리의 다른 글
Optional Chaining (0) | 2018.09.18 |
---|---|
Deinitialization (0) | 2018.09.18 |
Initialization (0) | 2018.09.17 |
Inheritance (0) | 2018.08.30 |
Methods (0) | 2018.08.30 |
Properties (0) | 2018.08.30 |
Structures and Classes (1) | 2018.08.30 |
Enumerations (0) | 2018.08.30 |