[Swift] 서브스크립트 Subscript

Bibi·2022년 3월 10일
0

[Swift] 서브스크립트 Subscript

Swift 프로그래밍 321-327

: 클래스, 구조체, 열거형에서 컬렉션/리스트/시퀀스 등 타입의 요소에 접근하는 단축 문법.

자신이 갖는 시퀀스/컬렉션/리스트 등의 요소를 반환 또는 설정할 때 주로 사용한다.

  • 별도의 getter, setter 구현 없이도 인덱스를 통해 값을 설정하거나 가져올 수 있다.
    • Array : someArray[index]와 같이 표현
    • Dictionary : someDictionary[key]와 같이 표현
  • 서브스크립트 오버로딩 Subscript Overloading : 필요한 만큼 얼만든지 서브스크립트를 구현할 수 있다.
  • 통상 하나의 매개변수를 갖는다 (여러 매개변수를 가질 수도 있다)
  • 매개변수의 타입과 리턴타입에는 제한이 없다

서브스크립트 문법

인스턴스 이름 뒤에 대괄호로 감싼 값을 써줌으로써 인스턴스 내부 특정 값에 접근할 수 있다.

문법 자체는 연산프로퍼티나 인스턴스 메서드 문법과 유사하다.

  • subscript키워드를 사용해 정의
  • 서브스크립트 정의는 각 타입의 구현부 또는 타입의 익스텐션 구현부에 한다.
// 읽기/쓰기 서브스크립트
subscript(index: Int) -> Int {
    get { 
      // 적절한 서브스크립트 결괏값 반환
    }
  
    set(newValue) {
      // 적절한 설정자 역할 수행
    }
}

// 읽기 전용 서브스크립트
subscript(index: Int) -> Int {
    get {
       // 적절한 서브스크립트 값 반환
    }
}

subscript(index: Int) -> Int {
   // 적절한 서브스크립트 결과값 반환 (get{} todfir rksmd)
}
  • setter에서 파라미터를 생략하면, newValue로 설정자의 암시적 전달인자에 접근할 수 있다.

서브스크립트 구현

  • 여러 개의 매개변수를 가질 수 있음
  • 매개변수 기본값을 가질 수 있음
  • 입출력 매개변수는 가질 수 없음
  • 여러 개의 서브스크립트도 구현 가능 - 시그니처를 다르게 하여 여러 용도로 서브스크립트 사용 가능
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 = 0) -> Student? {
    get {
     	  if index < self.number {
      	return self.students[index]
	   		 }
  	  	return nil
    }
    
    set {
      guard var newStudent: Student = newValue else { 
        /// 예를 들어 School[1] = Student(name: "bibi") 일때 newValue가 Student(name: "bibi")임
        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 { 
        /// 예를 들어 School["bibi"] = 1 일때 newValue가 1임
        return
      }
      
      if number > self.number {
        number = self.number
        self.number += 1
      }
      
      let newStudent: Student = Student(name: name, number: number)
      self.students[number] = newStudent
     
    }
    
    subscript(name: String, number: Int) -> Student? {
      return self.students.filter { $0.name == name && $0.number == number }.first
    }
  }
}

let highSchool: School = School()
highSchool.addStudents(names: "Mijeong", "Juhyun", "Jiyoung")

let aStudent: Student? = highSchool[1]
print("\(aStudent?.number)\(aStudent?.name)" // Optional(1)Optional("Juhyun")
print(highSchool[]?.name) // Optional("Mijeong") - 매개변수 기본값 사용

타입 서브스크립트

인스턴스가 아니라 타입 자체에서 사용할 수 있는 스크립트.

  • subscript앞에 static 키워드를 붙이면 됨.
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

0개의 댓글