[스위프트 프로그래밍-17장] 서브스크립트

sanghee·2021년 11월 22일
0
post-thumbnail

이 글은 스위프트 프로그래밍(3판, 야곰 지음)을 읽고 간단하게 정리한 글입니다. 책에 친절한 설명과 관련 예제 코드들이 있으므로 직접 사서 읽기를 추천합니다.

17.0 소개

서브스크립트

서브스크립트란 컬렉션, 클래스, 구조체, 열거형, 리스트, 시퀸스 등 타입의 요소에 접근하는 단축 문법이다.

Array[index], Dictionary[key]

17.1 서브스크립트 문법

[ ]

📌키워드: 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 {
    // 적절한 서브스크립트 값 반환
}

17.2~3 서브스크립트 구현과 복수 서브스크립트

서브스크립트를 통해 School 내의 students 배열에서 인덱스에 해당하는 학생을 반환한다.

1. Student 모델

학생 모델은 이름과 나이 프로퍼티를 가지고 있다.

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

2. School 클래스

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

3. 서브스크립트 정의하기

  1. students의 인덱스에 해당하는 학생을 반환하는 서브스크립트를 구현한다. get과 set을 구현하였기에 읽고 쓰는 것이 가능하다.
  2. 이름을 받아 해당 이름을 가진 첫번째 학생을 반환한다.
  3. 이름과 나이를 받아 해당 이름과 나이를 가진 첫번째 학생을 반환한다.
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
    }
}

4. 서브스크립트 사용하기

  1. highSchool에는 A, B, C, D, E학생이 있다.

  2. 서브스크립트의 index 기본값은 0이므로 첫번째 학생이 반환된다.

  3. 인덱스를 통해 학생에 접근하여 값을 읽거나 쓰는 것도 가능하다.

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")

17.4 타입 서브스크립트

📌키워드: 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과 class의 차이점?

타입 static 키워드는 자식 클래스에서 override할 수 없도록 한다. 반면 class 키워드를 사용한 경우엔 가능하다.

profile
👩‍💻

0개의 댓글