Subscript?

서브 스크립트는 클래스, 구조체, 열거형에 타입의 요소로 접근할 수 있게 해주는 문법이다.서브스크립트는 별로도 Getter, Setter를 설정하지 않아도 값을 가져오거나, 입력하는게 가능하다.

한 타입에 여러개의 서브스크립트를 정의할 수 있으며, 다른 타입을 인덱스로 갖는 여러개의 서브스크립트 또한 중복 정의 할 수 있다.

Subsrcipt 문법

서브 스크립트는 인스턴스의 이름뒤에 대괄호를 써서, 인스턴스 내부의 특정 값에 접근할 수 있다.

subscript(index: Int) -> Int {
	get {
    	// 적절한 서브 스크립트 결괏값
    }

    set(newValue) {
    	// 적절한 설정자 역할
    }
}

위의 코드는 서브스크립트의 기본적인 구조이다.값을 가져올때, 접근할때의 적절한 결괏값을 지정해주고 사용하면 된다.

subscript(index: Int) -> Int {
    get {
        // 적적한 서브스크립트 결괏값
    }
}

subscript(index: Int) -> Int {
	// 적적한 서브스크립트 결괏값
}

두 번째 코드의 두 서브스크립트는 사실 같은 역할을 한다.이유는 첫번째 코드는 읽기전용으로 구현된 코드이고, 아래쪽에 아무것도 적지 않은 코드도 읽기전용의 역할을 하기 때문이다!

Subscript 구현

서브스크립트는 아까도 말했듯 요소에 접근할 수 있게끔 해주는 문법이다.따라서 구조체, 열거형, 클래스 등에서 사용할 수 있다.

struct Student {
    var name: String
    var number: Int
}

class School {

    var number: Int = 0
    var students: [Student] = [Student]()

    func addStudent(name: String) {
        let student: Student = Student(name: name, number: self.number)
        self.students.append(student)
        self.number += 1
    }

    func addStudents(names: String...) {
        for name in names {
            self.addStudent(name: name)
        }
    }

    subscript(index: Int) -> Student? {
        if index < self.number {
            return self.students[index]
        }

        return nil
    }
}

let highSchool: School = School()

highSchool.addStudents(names: "ByeongYun", "JiYun", "SangHee", "Junsik")

let aStudent: Student? = highSchool[1]
print("\\(aStudent?.number) \\(aStudent?.name)") // Optional(1) Optional("JiYun")

좀 길어진 코드에서 서브스크립트만 쏙 빼와보겠다.

subscript(index: Int) -> Student? {
    if index < self.number {
        return self.students[index]
    }

    return nil
}

이 서브스크립트의 역할은 인덱스를 받아와서 그 인덱스가 유효한 인덱스일 경우에 Student 구조체(인스턴스)를 반환하는 역할이다.

이렇게 배열처럼 구조체에 접근할 수 있게 끔 해주는 것이 서브스크립트이다.

복수 서브스크립트

아까 설명 때 하나의 타입이 여러개의 서브스크립트를 가질 수 있다고 했었다.다양한 매개변수를 사용하여 서브스크립트를 구현하면, 다양하게 서브스크립트를 사용할 수 있다.

subscript(index: Int) -> Student? { // 첫 번째 서브스크립트
    get {
        if index < self.number {
            return self.students[index]
        }

        return nil
    }

    set {
        guard var newStudent: Student = newValue else {
            return
        }

        var number: Int = index

        if index > self.number {
            number = self.number
            self.number += 1
        }

        newStudent.number = number
        self.students[number] = newStudent
    }
}

첫 번째 서브스크립트는 아까 요구한 인덱스의 구조체를 가져오는 역할도 하고, 특정 번호의 학생을 할당하는 서브스크립트이다.