서브 스크립트 (Subscripts)
클래스, 구조체, 열거형은 collection, list, sequence의 멤버 요소에 접근할 수 있는 단축키인 서브 스크립트를 정의할 수 있다.
값의 설정 및 검색을 위한 별도의 메서드 없이 인덱스로 값을 설정하고, 조회하기 위해서 서브 스크립트를 사용한다.
예를 들어 someArray[index] 로 array의 인스턴스 요소에 접근, someDictionary[key] 로 dictionary 인스턴스 요소에 접근한다.
여러 개의 서브스크립트를 정의할 수 있고, 서브 스크립트 overload는 서브 스크립트의 인덱스 값에 따라 선택된다.
서브 스크립트는 단일 차원으로 제한되지 않고 사용자 타입에 맞춰 여러 개의 입력 파라미터로 서브 스크립트를 정의할 수 있다.
서브 스크립트 구문 (Subscript Syntax)
subscript(index: Int) -> Int {
get {
// 값을 반환하는 로직 작성
}
set(newValue) { // 👈🏻 newValue의 타입은 반환 값의 타입과 동일, default = newValue
// 셋팅하는 로직 작성
}
}
// read-only 인 경우에는 get {} 생략 가능
subscript(index: Int) -> Int {
// 값을 반환하는 로직 작성
}
인스턴스 뒤에 대괄호에 값을 작성해 타입의 인스턴스를 조회할 수 있다.
인스턴스 메서드 구문이나 연산 프로퍼티와 비슷하다.
subscript 키워드로 서브 스크립트 정의를 작성하고, 인스턴스 메서드와 같은 방법으로 하나 이상의 입력 파라미터와 반환 타입을 작성한다.
인스턴스 메서드와는 다르게 서브 스크립트는 읽기-쓰기 또는 읽기 전용이 될 수 있다.
연산 프로퍼티처럼 getter, setter를 통해 동작하게 된다.
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimeTable(multiplier: 3)
print("3의 6배는 \(threeTimesTable[6])") // 3의 6배는 18
💡 n-배-테이블은 수학적 규칙을 기반으로 합니다.
threeTimesTable[someIndex] 를 새로운 값을 설정하는 것은 적절하지 않으므로 TimesTable 의 서브 스크립트는 읽기전용(read-only) 서브 스크립트로 정의됩니다.
서브 스크립트 사용 (Subscript Usage)
서브 스크립트는 사용되는 컨텍스트에 따라 의미가 다르다.
일반적으로 서브 스크립트는 콜렉션, 목록, 또는 시퀀스에 멤버 요소에 접근하는 바로가기로 사용된다.
예를 들어 Swift의 Dictionary 타입은 Dictionary 인스턴스에 저장된 값을 설정하고, 조회하기 위해 서브 스크립트를 구현한다.
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] // 3개의 키-값 [String: Int] 딕셔너리 초기화
numberOfLegs["bird"] = 2
Dictionary 서브 스크립에 대한 내용은 Accessing and Modifying a Dictionary를 참고하자.
💡Swift의 Dictionary 타입은 optional 타입을 가지고 반환하는 서브 스크립트인 key-value 서브 스크립트를 구현하고 있다. 위의 numberOfLegs 딕셔너리에서 key-value 서브 스크립트는 타입 Int? 또는 optional Int 깂을 반환한다.
Dictionary 타입은 모든 키에 값이 있지 않다는 사실을 모델링하고 키의 값에 nil을 할당해 키의 값을 삭제하는 방법을 제공하기 위해서 optional 서브 스크립트 타입을 사용한다.
서브 스크립트 옵션 (Subscript Options)
서브 스크립트는 여러 개의 입력 파라미터를 가질 수 있고, 입력 파라미터는 어떤 타입도 가능하다.
또한 서브 스크립트는 어떤 타입도 반환할 수 있다.
함수처럼 서브 스크립트는 가변 파라미터(Variadic Parameters)와 파라미터 기본값(Default Parameter Values)을 가질 수 있다. 그러나 함수와는 다르게 in-out 파라미터를 사용할 수는 없다.
클래스, 구조체에서 필요한 만큼 서브 스크립트를 구현할 수 있고, 이때 서브 스크립트 대괄호 값의 타입을 기반으로 유추해 적절한 서브 스크립트를 제공하게 된다.
이렇게 여러 개의 서브 스크립트를 정의하는 것을 **서브 스크립트 오버로딩(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 * column) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * column) + column] = newValue
}
}
}
Matrix는 rows, columns 2개의 파라미터를 가지고 rows * columns 값을 저장할 수 있는 grid 배열을 가진다.
행렬의 각 위치는 0.0의 초기값이 주어진다.
초기화는 Creating an Array with a Default Value 배열을 기본값으로 초기화하는 방법을 살펴보자.
var matrix = Matrix(rows: 2, columns: 2)
2행 2열을 가지는 새로운 Matrix 인스턴스를 생성한다.
Matrix 인스턴스의 grid 배열은 아래와같이 왼쪽 상단에서 오른쪽 하단으로 읽는 것처럼 행렬의 평면화 버전이다.

행렬의 값은 콤마로 구분된 서브 스크립트에 행과 열 값을 전달해 설정할 수 있다.
서브 스크립트의 setter를 호출한다.
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

Matrix의 서브 스크립의 getter, setter는 둘 다 row, column이 유효한지 판단하기 위해 assertion이 포함된다.
Assertion은 유효한지 판단 하기 위해서 indexIsValid(row: column:) 메서드를 포함하고 있다.
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
let someValue = matrix[2, 2] // [2, 2]는 matrix의 범위를 넘어가므로 assert를 호출하게 한다
타입 서브 스크립트 (Type Subscripts)
인스턴스 서브 스크립트는 특정 타입의 인스턴스를 호출하는 서브 스크립트이다.
타입 자체에서 호출되는 서브 스크립트도 정의할 수 있다.
이를 타입 서브 스크립트(type subscript)라고 한다. Script 앞에 static 키워드를 작성하면 된다.
클래스의 경우에는 슈퍼 클래스의 서브 스크립트의 구현을 재정의 할 수 있게 class 키워드를 사용할 수 있다.
enum Plant: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
static subscript(n: Int) -> Plant {
return Plant(rawValue: n)!
}
}
let mars = Planet[4]
print(mars`)
서브 스크립트 (Subscripts)
클래스, 구조체, 열거형은 collection, list, sequence의 멤버 요소에 접근할 수 있는 단축키인 서브 스크립트를 정의할 수 있다.
값의 설정 및 검색을 위한 별도의 메서드 없이 인덱스로 값을 설정하고, 조회하기 위해서 서브 스크립트를 사용한다.
예를 들어
someArray[index]로 array의 인스턴스 요소에 접근,someDictionary[key]로 dictionary 인스턴스 요소에 접근한다.여러 개의 서브스크립트를 정의할 수 있고, 서브 스크립트 overload는 서브 스크립트의 인덱스 값에 따라 선택된다.
서브 스크립트는 단일 차원으로 제한되지 않고 사용자 타입에 맞춰 여러 개의 입력 파라미터로 서브 스크립트를 정의할 수 있다.
서브 스크립트 구문 (Subscript Syntax)
인스턴스 뒤에 대괄호에 값을 작성해 타입의 인스턴스를 조회할 수 있다.
인스턴스 메서드 구문이나 연산 프로퍼티와 비슷하다.
subscript키워드로 서브 스크립트 정의를 작성하고, 인스턴스 메서드와 같은 방법으로 하나 이상의 입력 파라미터와 반환 타입을 작성한다.인스턴스 메서드와는 다르게 서브 스크립트는 읽기-쓰기 또는 읽기 전용이 될 수 있다.
연산 프로퍼티처럼 getter, setter를 통해 동작하게 된다.
서브 스크립트 사용 (Subscript Usage)
서브 스크립트는 사용되는 컨텍스트에 따라 의미가 다르다.
일반적으로 서브 스크립트는 콜렉션, 목록, 또는 시퀀스에 멤버 요소에 접근하는 바로가기로 사용된다.
예를 들어 Swift의 Dictionary 타입은 Dictionary 인스턴스에 저장된 값을 설정하고, 조회하기 위해 서브 스크립트를 구현한다.
Dictionary 서브 스크립에 대한 내용은 Accessing and Modifying a Dictionary를 참고하자.
서브 스크립트 옵션 (Subscript Options)
서브 스크립트는 여러 개의 입력 파라미터를 가질 수 있고, 입력 파라미터는 어떤 타입도 가능하다.
또한 서브 스크립트는 어떤 타입도 반환할 수 있다.
함수처럼 서브 스크립트는 가변 파라미터(Variadic Parameters)와 파라미터 기본값(Default Parameter Values)을 가질 수 있다. 그러나 함수와는 다르게 in-out 파라미터를 사용할 수는 없다.
클래스, 구조체에서 필요한 만큼 서브 스크립트를 구현할 수 있고, 이때 서브 스크립트 대괄호 값의 타입을 기반으로 유추해 적절한 서브 스크립트를 제공하게 된다.
이렇게 여러 개의 서브 스크립트를 정의하는 것을 **서브 스크립트 오버로딩(subscript overloading)**라고 한다.
Matrix는 rows, columns 2개의 파라미터를 가지고 rows * columns 값을 저장할 수 있는 grid 배열을 가진다.
행렬의 각 위치는 0.0의 초기값이 주어진다.
초기화는 Creating an Array with a Default Value 배열을 기본값으로 초기화하는 방법을 살펴보자.
2행 2열을 가지는 새로운 Matrix 인스턴스를 생성한다.
Matrix 인스턴스의 grid 배열은 아래와같이 왼쪽 상단에서 오른쪽 하단으로 읽는 것처럼 행렬의 평면화 버전이다.
행렬의 값은 콤마로 구분된 서브 스크립트에 행과 열 값을 전달해 설정할 수 있다.
서브 스크립트의 setter를 호출한다.
Matrix의 서브 스크립의 getter, setter는 둘 다 row, column이 유효한지 판단하기 위해 assertion이 포함된다.
Assertion은 유효한지 판단 하기 위해서
indexIsValid(row: column:)메서드를 포함하고 있다.타입 서브 스크립트 (Type Subscripts)
인스턴스 서브 스크립트는 특정 타입의 인스턴스를 호출하는 서브 스크립트이다.
타입 자체에서 호출되는 서브 스크립트도 정의할 수 있다.
이를 타입 서브 스크립트(type subscript)라고 한다. Script 앞에
static키워드를 작성하면 된다.클래스의 경우에는 슈퍼 클래스의 서브 스크립트의 구현을 재정의 할 수 있게
class키워드를 사용할 수 있다.