본문 바로가기

iOS/Swift

Swift) 서브스크립트(Subscript) 정복하기

 

 

 

안녕하세요!?! 소들입니다!!!!!!!!! :D

오늘은 서브스크립트(Subscript)에 대해 알아볼 거예요!!!

이렇게 하나하나 Swift를 정복하다보면.. 언젠가 Swift 왕이 되어 있기를 간절히 바라며.....👑

 

이번에도 쉬운 내용이니 후딱 끝내겠습니다 :)

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. 서브스크립트(Subscript)란?

 

클래스, 구조체, 열거형에서 시퀀스의 멤버 요소에 접근하기 위한 바로가기 첨자로,

단일 타입에 여러 서브스크립트를 정의할 수 있다

 

정의만 보면 이게 도대체 뭔 🐶소리인지^^;;;

사실 이름이 조금 어려울 뿐이지, 우린 지금껏 아~주 자연스럽게 서브스크립트를 써왔음

정의에서 "시퀀스" 멤버 요소에 접근하기 위한 것이라 했짢음!?!

 

대표적으로 우리가 배열을 사용하면서  원소에 값에 접근할 때 

 

 

let nums: [Int= [1234]
 
nums[0]                // 1
nums[1]                // 2

 

 

이렇게 [] 대괄호 안에 index를 넣어줘서 멤버 요소에 접근하잖음?!?!

이것이 바로 서브스크립트임!!!! 실제로 저 배열의 []의 정의를 따라가보면,

 

 

 

 

이렇게 정의되어 있음!!!!!!

아하! 배열의 서브스크립트는 parameter로 Int형을 index로 받고, 

해당 index에 해당하는 Element를 반환하는 형태구나! 라는 것을 알 수 있음 :)

 

한 가지 더 예를 보자면, 이번엔 딕셔너리로 봐보겠음!!!!!

우리가 딕셔너리에서 Value에 접근할 때

 

 

let dict: [StringInt= ["one"1"two"2]
 
dict["one"]             // 1
dict["two"]             // 2

 

 

이렇게 [] 대괄호 안에 Key값을 넣어줘서 Value에 접근하잖음?!?!

이것이 바로바로 서브스크립트임!!!! 저 딕셔너리 []의 정의를 따라가보면,

 

 

 

 

 

이렇게 정의되어 있음 :)

아하! 딕셔너리의 서브스크립트는 Prameter로 Key를 받고,

해당 Key에 해당하는 Value를 반환하는 형태구나! 라는 것을 알 수 있음!

 

 

자, 서브스크립트가 어떤 것인지 이제 감이 완벽히 왔을 거라 믿고,

그럼 서브스크립트를 직접 사용하는 방법에 대해 알아봅세~.~

 

+

(더 나아간다면, 위에 딕셔너리의 서브스크립트 선언에서 일반적인 메서드 형태라면,

key는 argument label이자 parameter name이니까, 서브스크립트를 호출할 당시

[key: ] 이렇게 호출해야하는 거 아닌가여? 란 의문이 들 수 있는데, 이는 뒤에서 다룰 거니 일단 스킵!!)

 

 

 

 

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

 

 

subscript 키워드로 작성하며 하나 이상의 파라미터와 반환 값을 지정한다

파라미터나 리턴형을 생략할 수 없고, getter와 setter 모두 구현할 수 있다

get-only는 가능하지만, set-only는 불가하다 (getter 생략 불가)

 

 

subscript(index: Int-> Int {
    get {
    }
    set(newValue) {
    }
}

 

 

서브스크립트 정의는 위와 같은 방식으로 하는데, 마치 연산 프로퍼티와 비슷하고

실제로 연산 프로퍼티와 get/set의 성질은 거의 비슷함!!!!

setter의 경우 파라미터를 생략하면 newValue로 접근할 수 있는 것 또한 같고,

get-only일 경우 get 구문 생략 가능한 것도 같음(이해 안가면 연산 프로퍼티부터 공부하시길..!)

 

음.. 위 선언만으론 잘 와닿지 않을 수 있으니 다른 예제로 보겠음!!!!

우리가 알고리즘을 풀 때나 가끔 String을 쓸 때 너무도 원하는 것...

String도 배열처럼 [index]로 접근하고 싶다!!!!!!!!! 느낄 ㄸㅐ 있지 않음!?!?!

 

 

let sodeul = "Hello, Sodeul!"
sodeul[0]               // error!!

 

 

sodeul[0]을 쓰면, 배열 처럼 "H"가 반환되면 참 좋겄다만 실제론 에러임ㅎ

어떤 에러냐? 해당 서브스크립트를 사용할 수 없다는 에러임!! 근데 우린 이제 서브스크립트가 뭔지 알았잖음 :) ??

따라서  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])
    }
}
 

 

 

위와 같이 extension을 통해 서브스크립트를 직접 구현해주면,

 

 

let sodeul = "Hello, Sodeul!"
sodeul[0]           // Optional("H")
sodeul[100]         // nil

 

 

이렇게 []를 통해 내가 원하는 index의 문자에 접근할 수 있음!!ㅎㅎ

이런 것이 바로 서브스크립트..!

 

 

 

2-1. 만약 Argument Label을 사용하고 싶다면..

 

위에서 잠깐 의문점?이 들 수 있다고 말했는데,

서브스크립트는 파라미터 선언 당시 Argument Label을 _로 처리해주지 않아도,

Argument Label로 사용되지 않음..! Only Parameter Name..!!

 

 

subscript(indexInt-> Int {
    get {
    }
    set(newValue) {
    }
}

 

 

따라서, 선언은 저렇지만 실제 서브스크립트를 호출할 때도

index란 Argument Label 없이 호출하는 것임..! 근데 만약 굳이 굳이 써주고 싶다면,

 

 

subscript(index indexInt-> Int {
    get {
    }
    set(newValue) {
    }
}

 

 

이렇게 써주면... 뭐 실제 서브스크립트를 사용할 때도,

 

 

subscript[index: 0]

 

 

이렇게 Argument Label을 넣어줄 순 있는데...

웬만해선 ................ 쓰지...... 않는........... 것이.......(안 쓰는 데엔 다 이유가....)

 

 

 

 

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

 

뭐..... 위에서 다 봤찌만...

 

 

struct Stack {
    var stack: [Int= [012345]
 
    subscript(index: Int-> Int {
        get {
            return stack[index]
        }
        set {
            stack[index] = newValue
        }
    }
}

 

 

만약 Stack이란 구조체에 서브스크립트를 위처럼 구현했을 경우,

 

 

var stack: Stack = .init()
 
stack[0]            // 서브스크립트 getter 접근
stack[1= 2        // 서브스크립트 setter 접근

 

 

이렇게 []를 통해 getter / setter에 접근할 수 있음 :)

 

 

 

 

4. 타입 서브스크립트(Type Subscript)

 

타입 프로퍼티 / 타입 메서드에서 공부 했듯이

서브스크립트 또한 타입 서브스크립트로 선언이 가능함!!!!

(인스턴스 vs 타입은 이전에 다뤘으니 깊게 안하고 넘어감!)

 

 

struct Stack {
    static var stack: [Int= [0123]
 
    static subscript(index: Int-> Int {
        return stack[index]
    }
}
 

 

 

이렇게!! 

오버라이딩이 불가하다면 static / 가능하다면 class로 선언해주면

타입 서브스크립트가 되는 것임!!!

 

 

Stack[0]        // 0
Stack[1]        // 1

 

 

실제로, 인스턴스 없이 "타입 이름"에 대고 호출이 가능함!

 

 

 

 

 

 

 

.

.

.

서브스크립트 포스팅 끝:)

잘못된 점 & 궁금한 점은 언제든!! 댓글 주세요

피드백 대환영입니다~



Calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
최근 댓글
Visits
Today
Yesterday