이 글은 스위프트 프로그래밍(3판, 야곰 지음)을 읽고 간단하게 정리한 글입니다. 책에 친절한 설명과 관련 예제 코드들이 있으므로 직접 사서 읽기를 추천합니다.
서브스크립트란 컬렉션, 클래스, 구조체, 열거형, 리스트, 시퀸스 등 타입의 요소에 접근하는 단축 문법이다.
📌키워드: subscript
대괄호로 감싼 값을 써줌으로서 인스턴스 내부의 값에 접근한다. 키워드인 subscript를 사용하여 정의한다.
@frozen public struct Array<Element> {
@inlinable public subscript(index: Int) -> Element
@inlinable public subscript(bounds: Range<Int>) -> Slice<Array<Element>>
...
}
let array = [1, 2, 3, 4, 5]
parray[1] // 2
array[0...2] // [1, 2, 3]
Array에서 서브스크립트가 어떻게 정의되어 있는지?
subscript(index: Int) -> Int {
get {
// 적절한 서브스크립트 결괏값 반환
}
set {
// 적절한 설정자 역할 수행
}
}
읽기전용 서브스크립트인 경우 아래와 같이 표현할 수 있다.
subscript(index: Int) -> Int {
get {
// 적절한 서브스크립트 결괏값 반환
}
}
subscript(index: Int) -> Int {
// 적절한 서브스크립트 값 반환
}
서브스크립트를 통해 School 내의 students 배열에서 인덱스에 해당하는 학생을 반환한다.
학생 모델은 이름과 나이 프로퍼티를 가지고 있다.
struct Student {
var name: String
var age: Int
}
class School {
var count: Int = 0
var students: [Student] = []
func addStudent(name: String) {
let student = Student(name: name, age: count)
students.append(student)
count += 1
}
func addStudents(names: [String]) {
for name in names {
addStudent(name: name)
}
}
...
}
class School {
...
1. subscript(index: Int = 0) -> Student? {
get {
return (index < count) ? students[index] : nil
}
set {
guard let newStudent = newValue else { return }
students[index] = newStudent
}
}
2. subscript(name: String) -> Student? {
return students.filter { $0.name == name }.first
}
3. subscript(name: String, age: Int) -> Student? {
return students.filter { $0.name == name && $0.age == age }.first
}
}
highSchool에는 A, B, C, D, E학생이 있다.
서브스크립트의 index 기본값은 0이므로 첫번째 학생이 반환된다.
인덱스를 통해 학생에 접근하여 값을 읽거나 쓰는 것도 가능하다.
let highSchool = School()
1. highSchool.addStudents(names: ["A", "B", "C", "D", "E"])
2. highSchool[]?.name // Optional("A")
3. let studentB = highSchool[1]
studentB?.name // Optional("B")
3. highSchool[1] = Student(name: "Z", age: 0)
highSchool[1]?.name // Optional("Z")
let studentC = highSchool["C"]
studentC?.name // Optional("C")
// highSchool["C"] = Student(name: "G", age: 0) // ERROR!
let studentD = highSchool["D", 3]
studentD?.name // Optional("D")
📌키워드: static, class(클래스의 경우)
타입 서브스크립트는 이전에 본 것처럼 인스턴스에서 사용하는 것이 아닌 타입 자체에서 사용하는 서브스크립트이다.
School이라는 열거형 타입에서 [2]로 사용하였다.
enum School: Int {
case elementary = 1, middle, high, university
static subscript(level: Int) -> School? {
return Self(rawValue: level) // == School(rawValue: level)
}
}
let school: School? = School[2]
print(school) // School.middle
타입 static 키워드는 자식 클래스에서 override할 수 없도록 한다. 반면 class 키워드를 사용한 경우엔 가능하다.