Subscript 알아보기

Tabber·2021년 12월 8일
0

Swift

목록 보기
5/5

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
    }
}

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

subscript(name: String) -> Int? {  // 두 번째 서브스크립트
    get {
        return self.students.filter { $0.name == name }.first?.number
    }

    set {
        guard var number: Int = newValue else {
            return
        }

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

        let newStudent: Student = Student(name: name, number: number)
       self.students[number] = newStudent
    }
}

두 번째 서브스크립트는 학생의 이름을 전달받아서 해당하는 학생이 있으면 번호를 반환하거나 특정 학생의 이름을 해당 번호에 할당하는 서브스크립트이다.

이렇게 하나의 타입에서 여러개의 서브스크립트를 생성하고 사용할 수 있다.

타입 서브스크립트

지금까지 설명한 서브스크립트는 인스턴스에서 사용할 수 있는 서브스크립트이다.
그러나 타입 서브스크립트는 조금 다르게 인스턴스가 아니라 타입 자체에 사용할 수 있는 서브크립트이다.

enum School: Int {
    case elementary = 1, middle, high, university

    static subscript(level: Int) -> School? {
        return Self(rawValue: level)
        // return School(rawValue: level) 과 같은 표현이다.
    }
}

let school: School? = School[2]

print(school)  // School.middle

타입 서브스크립트를 구현하려면 스크립트 앞에 static키워드를 붙여서 구현할 수 있다.
클래스의 경우에는 class 키워드를 사용하면 된다.

정리

오늘은 서브스크립트의 정의, 서브스크립트의 문법, 구현, 복수 서브스크립트, 타입 서브스크립트에 대해 알아보았다.
서브스크립트는 배열과 같은 느낌으로 요소에 접근할 수 있기 때문에 정말 편리한 기능 중 하나이다. 이 점 꼭 기억하고 나중에 사용해보도록 하자.

profile
iOS 정복중인 Tabber 입니다.

0개의 댓글