서브스크립트
클래스, 구조체, 열거형에는 컬렉션, 리스트, 시퀀스 등 타입의 요소에 접근하는 단축 문법 서브스크립트( 1Subscript
)를 정의할 수 있다.
별도의 설정자(Setter
)와 접근자(Getter
)등의 메서드를 구현하지 않아도 인덱스를 통해 값을 설정하거나 가져올 수 있다.
someArray[index]
//someArray인스턴스의 index를 통해 해당 인덱스 값 접근
someDictionary[key]
// someDictionary라는 Dictionary의 key를 통해 해당값을 가져옴
- 클래스, 구조체는 필요한 만큼 서브스크립트 구현 가능
- 서브스크립스트를 여러 개 구현해도 외부에서 서브스크립트를 사용할 땐, 서브스크립트를 사용할 때 전달한 값 타입을 유추해 적절한 서브스크립트를 적절한 것으로 선택하여 실행함
- 이것을 중복 정의(
Subscript Overloading
)라고 함 - 타입에 따라 여러 매개변수를 갖는 경우도 존재함 (보통은 하나의 매개변수를 가짐)
- 매개변수의 타입과 반환 타입에는 제한이 없음
- 여러 개의 매개변수를 가질 수 있고, 매개변수 기본값을 가질 수 있음
- 입출력 매개변수(
in-out parameters
)는 가질 수 없음
서브스크립트 문법
subscript 키워드
에 대괄호(_:)
를 붙혀 사용함subscript(_:)
- 인스턴스 내부의 특정 값에 접근 가능
- 연산 프로퍼티(접근자, 설정자)나 인스턴스 메서드 문법과 유사한 형태를 지님
- 매개변수의 개수, 타입, 반환 타입 등을 지정하며, 읽고 쓰기가 가능하도록 구현하거나 읽기 전용으로만 구현 가능
subscript
를 정의하는 코드는 각 타입 구현부 또는 타입의 익스텐션 구현부에 위치해야 함get-only
는 가능하지만,set-only
는 불가
let nums: [Int] = [1, 2, 3, 4]
nums[0] //1
nums[1] //2
nums[0]
이것이 서브스크립트 이다. 대괄호 안에 인덱스를 넣어 요소에 접근 하는것!
let numbers: [String: Int] = ["one": 1, "two": 2, "three": 3]
numbers["one"]
numbers["two"]
numbers["three"]
subscript(index: Int) -> Int {
get {
//적절한 서브스크립트 결괏값을 반환함
}
set(newValue) {
//적절한 설정자 역할을 수행함
}
}
위 코드의 설정자 set(newValue)
의 타입은 서브스크립트 반환 타입과 동일하다. 연산 프로퍼티에서 그랬던 것처럼 매개변수를 따로 명시하지 않으면 전달 인자 newValue
를 사용할 수 있다. (set
의 매개변수를 생략한다면 반드시 newValue
키워드를 사용해야 함)
또, 읽기 전용 프로퍼티를 구현할 땐 get
이나 set
키워드를 사용하지 않고 적절한 값만 반환해주는 형태로 구현해도 된다.
subscript(index: Int) -> Int {
get {
// 적절한 서브스크립트 값 반환
}
}
subscript(index: Int) -> Int {
// 적절한 서브스크립트 결괏값 반환
}
이 두 서브스크립트는 동일한 역할을 한다. get
메서드 없이 단순하게 값만을 반환하도록 구현하면 바로 읽기 전용이 되는것이다. 이렇게 연산 프로퍼티와 아주 유사한것을 확인할 수 있다.
String
도 인덱스로 접근 하고 싶지만 아래처럼 접근하면 에러가 난다.
let Seogun = "서근 개발블로그"
Seogun[1] //error
하지만 서브스크립트를 사용해서 String
을 확장해 다음과 같이 작성한다면 가능하다.
extension String {
subscript(idx: Int) -> String? {
guard (0..<count).contains(idx) else {
return nil
}
let target = index(startIndex, offsetBy: idx)
return String(self[target])
}
}
let Seogun: String = "서근 개발블로그"
Seogun[0] // 서
Seogun[1] // 근
Seogun[40] // nil
서브스크립트 구현
위에서 말했듯이 서브스크립트는..
- 자신이 가지는 시퀀스, 컬렉션, 리스트 등의 요소를 반환하고 설정할 때 주로 사용
- 여러 개의 매개변수를 가질 수 있고, 매개변수 기본값을 가질 수 있음
- 입출력 매개변수는 가질 수 없음
이라고 했는데 이것을 잘 기억하고 아래 구현 코드를 살펴보도록 하자!
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? {
if index < self.number {
return self.students[index]
}
return nil
}
}
let highSchool: School = School()
highSchool.addStudents(names: "서근", "철수", "민지", "훈이", "석규")
let aStudent: Student? = highSchool[1]
print("\(aStudent?.number) \(aStudent?.name)") //Optional(1) Optional("철수")
Optional("철수")
print(highSchool[]?.name)
subsctript
는 School
클래스의 읽기 전용 서브스크립트 이고, 학생의 번호를 전달 인자로 전달받아서 자신의 students
프로퍼티 인덱스에 맞는 Student
인스턴스를 반환한다.
위 코드에서 subsctript(index: Int = 0)
으로 0을 매개변수 기본값으로 가졌지만, 필요하지 않으면 기본값이 없어도 된다.
타입 서브스크립트
여태까지 사용한 서브 스크립트는 인스턴스에서 사용할 수 있는 서브스크립트 이다.
- 타입 서브스크립트는 인스턴스가 아닌 타입 자체에서 사용 가능한 서브스크립트임
static 키워드
를 사용함- 클래스의 경우
class 키워드
를 사용할 수 있음
enum School: Int {
case elementary = 1, middle, high, university
static subscript(level: Int) -> School? {
return Self(rawValue: level)
}
}
let school: School? = School[2]
print(school) //Optional(School.middle)
struct Alphabet {
static var alphabets: [String] = ["a", "b", "c", "d"]
static subscript(index: Int) -> String {
return alphabets[index]
}
}
print("Alphabet 구조체의 첫 번째 인덱스 : \(Alphabet[0])")
//Alphabet 구조체의 첫 번째 인덱스 : a
print("Alphabet 구조체의 세 번째 인덱스 : \(Alphabet[2])")
//Alphabet 구조체의 세 번째 인덱스 : c
읽어주셔서 감사합니다 🤟
- 시퀀스(Sequence)는 직역하면 연속열이 될 수 있으며, 문자 그대로 개개의 원소들을 순서대로 하나씩 순회할 수 있는 타입을 의미한다. 간단하게 말해 Array나 Dictionary 등이 있다. [본문으로]
'SWIFT > Grammar' 카테고리의 다른 글
Swift : 기초문법 [상속#2 재정의 override] (0) | 2022.01.23 |
---|---|
Swift : 기초문법 [상속#1 - 클래스 상속(자식, 부모, 기반 클래스)] (0) | 2022.01.22 |
Swift: 기초문법 [모나드 - 컨텍스트, 함수객체, 모나드] (0) | 2022.01.20 |
Swift : 기초문법 [클로저 및 고차함수(map, filter, reduce)] (0) | 2022.01.19 |
Swift : 기초문법 [접근 제어 - open, public, internal, fileprivate, private] (0) | 2022.01.18 |