본 내용은 스위프트 프로그래밍 3판 (야곰 지음) 교재를 공부한 내용을 바탕으로 작성 하였습니다.
서브스크립트
의 정의는 다음과 같다.
서브스크립트: 클래스, 구조체, 열거형 내부의 컬렉션, 리스트, 시퀀스 등 타입 요소에 접근하는 문법
다시 말해 설정자(setter)나 접근자(getter)를 사용하지 않고 인덱스
를 통해 값을 가져올 수 있다는 것이다.
서브스크립트는 subscript
키워드를 사용하여 선언하며 형태는 인스턴스의 메서드와 비슷하다. 또한 연산 프로퍼티와 마찬가지로 읽고 쓰는 형태 혹은 읽기 전용(쓰기 전용은 불가능)으로 구현이 가능하다.
서브스크립트의 형태는 다음과 같다.
subscript(index: Int) -> Int {
get {
//서브스크립트 결과값 반환
}
set(newValue) {
//설정자 구현
}
}
서브스크립트의 형태의 set에서 newValue
는 연산 프로퍼티와 같이 매개변수를 구현하지 않으면 암시적 전달자로 사용 할 수 있다.
다음은 서브스크립트를 구현한 간단한 예시이다.
struct Student {
var name: String //학생 이름을 저장할 변수
}
class School {
var number: Int = 0
var students: [Int: Student] = [Int: Student]() //학생의 정보를 저장할 딕셔너리[번호: 학생]
func addStudent(student: Student) {
students[number] = student
number += 1
}
func addStudents(students: Student...) {
for student in students {
self.addStudent(student: student)
}
}
subscript(key: Int) -> Student? { //key을 받아 value를 반환하는 서브스크립트
if key < self.number {
return students[key]
}
return nil
}
}
let highSchool: School = School()
var studentLee: Student = Student(name: "이철수")
var studentKim: Student = Student(name: "김영희")
var studentSon: Student = Student(name: "손민준")
var studentPark: Student = Student(name: "박현우")
highSchool.addStudents(students: studentLee, studentKim, studentSon, studentPark)
let aStudent: Student? = highSchool[1]
print(aStudent)
School
클래스 내부에는 읽기 전용으로 구현된 서브스크립트
가 존재한다. 이 서브스크립트는 딕셔너리의 key
값을 매개변수로 받아 딕셔너리의 value
값을 return하는 서브스크립트이다.
물론 클래스나 구조체, 열거형에서 서브스크립트를 여러개 구현하는 것도 가능하다. 또한 서브스크립트의 매개변수를 여러개 사용하는것도 가능하다.
다음은 두개 이상의 서브스크립트를 구현한 코드이다.
struct Student {
var name: String //학생 이름을 저장할 변수
}
class School {
var number: Int = 0
var students: [Int: Student] = [Int: Student]() //학생의 정보를 저장할 딕셔너리[번호: 학생]
func addStudent(student: Student) {
students[number] = student
number += 1
}
func addStudents(students: Student...) {
for student in students {
self.addStudent(student: student)
}
}
//첫번째 서브스크립트
subscript(key: Int) -> Student? { //key값에 해당하는 value를 반환
get {
if key < self.number {
return students[key]
}
return nil
}
//새로운 학생 추가
set {
guard var newStudent: Student = newValue else {
return
}
var number = key
if number > self.number {
number = self.number
self.number += 1
}
students[number] = newStudent
}
}
//두번째 서브스크립트
subscript(name: String) -> Int? { //name에 해당하는 인스턴스의 key값 반환
get {
return self.students.filter { $0.1.name == name }.first?.key
}
}
//세번째 서브스크립트
subscript(key: Int, name: String) -> Student? { //key값과 name값에 해당하는 Student 인스턴스 반환
return self.students.filter { $0.0 == key && $0.1.name == name }.first?.value
}
}
let highSchool: School = School()
var studentLee: Student = Student(name: "이철수")
var studentKim: Student = Student(name: "김영희")
var studentSon: Student = Student(name: "손민준")
var studentPark: Student = Student(name: "박현우")
var studentHong: Student = Student(name: "홍수민")
highSchool.addStudents(students: studentLee, studentKim, studentSon, studentPark)
let aStudent: Student? = highSchool[1] //첫번째 서브스크립트 사용
print(aStudent)
highSchool[8] = studentHong //첫번째 서브스크립트의 set 메서드 사용
print(highSchool["홍수민"]) //두번째 서브스크립트 사용
print(highSchool["이철수"]) //두번째 서브스크립트 사용
print(highSchool[1, "김영희"]) //세번째 서브스크립트 사용
첫번째 서브스크립트
는 읽기와 쓰기를 모두 구현하여 key
에 해당하는 Student 인스턴스
를 반환하고, 두번째 서브스크립트
는 읽기만 구현하여 이름
를 매개변수로 전달 받아 해당하는 key
를 반환한다. 마지막으로 세번째 서브스크립트
는 매개변수를 두개 구현하여 해당하는 Student 인스턴스
를 반환하도록 하였다.
타입 서브스크립트
는 인스턴스 생성 상관없이 타입 자체에서 사용이 가능한 서브스크립트이다. subscript 키워드 앞에 static
키워드를 사용하여 선언한다.
다음은 타입 서브스크립트를 구현한 코드이다.
enum BaekjoonTier: Int {
case bronze = 1
case silver, gold
static subscript(tier: Int) -> BaekjoonTier? { //타입 서브스크립트
return Self(rawValue: tier) //원시 값에 해당하는 항목 반환
}
}
let myTier: BaekjoonTier? = BaekjoonTier[2]
print(myTier)
위와 같이 열거형 타입에 인덱스를 사용하여 해당하는 항목을 가져오는 코드를 구현하였다.