[Swift 프로그래밍] 서브스크립트(Subscript)

이정훈·2022년 6월 21일
0

Swift 기본

목록 보기
16/22
post-thumbnail

본 내용은 스위프트 프로그래밍 3판 (야곰 지음) 교재를 공부한 내용을 바탕으로 작성 하였습니다.

서브스트립트(Subscript)


서브스크립트의 정의는 다음과 같다.

서브스크립트: 클래스, 구조체, 열거형 내부의 컬렉션, 리스트, 시퀀스 등 타입 요소에 접근하는 문법

다시 말해 설정자(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)

위와 같이 열거형 타입에 인덱스를 사용하여 해당하는 항목을 가져오는 코드를 구현하였다.

profile
새롭게 알게된 것을 기록하는 공간

0개의 댓글