티스토리 뷰
배열이 아닌 struct에서 []로 접근했을 때 동작(?)하길래 훑어본 subscript..
우선 subscript 부터 알아보자
https://jusung.gitbook.io/the-swift-language-guide/language-guide/12-subscripts
다 알아보았습니다
저는 여기서 몇 개 발췌하고 배열이 아닌 struct에 []로 접근했을 때, 동작을 알아보겠습니다.
서브스크립트란?
ㄴ콜렉션, 리스트, 시퀀스 등 집합의 특정 멤버 엘리먼트에 간단하게 접근할 수 있는 문법입니다.
한 마디로 평소에 우리가 배열 접근할 때!
array[1] 이런식으로 [ ] '대괄호' 를 사용했는데요. 이 문법 자체를 "서브스크립트 subscript" 라고 합니다.
배열(Array) 인스턴스의 특정 엘리먼트는 someArray[index]문법으로,
사전(Dictionary) 인스턴스의 특정 엘리먼트는 someDictionary[key]로 접근할 수 있습니다.
이 글의 핵심은 >> 하나의 타입에 여러 서브스크립트를 정의할 수 있고 오버로드(Overload)도 가능합니다. << 사실 여기에 있는데요.
subscript(index: Int) -> Int {
get {
// 적절한 반환 값
}
set(newValue) {
// 적절한 set 액션
}
}
서브스크립트의 set에 대한 인자 값을 따로 지정하지 않으면 기본 값(default value)로 newValue를 사용합니다. 읽기 전용으로 선언하려면 get, set을 지우고 따로 지정하지 않으면 get으로 동작하게 되서 읽기 전용으로 선언됩니다.
subscript(index: Int) -> Int {
// 적절한 반환 값
}
위는 읽기 전용 subscript 입니다.
읽기 전용 + struct 로 확인 할 수 있는, 제가 찾던 예시가 위에 첨부된 링크에 있었는데요.
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// "six times three is 18" 출력
threeTimesTable이 배열이 아닌데 [6]이 가능한가 ? --> 가능. 왜냐면 [ ] 이 대괄호 자체가 subscript의 문법임 ㅇㅇ
[ ] 는 배열 접근시에만 사용하는게 아님. 배열 접근시 [ ] 도 사실은 subscript 인거임
그래서 threeTimesTable[6] 하면 이 6이라는 숫자가 재정의된 subscript(index: Int)의 index로 들어가게 되고,
그 return 값으로 처음 초기화시 지정해준 multiplier 3과 곱해져 18 이라는 Int 값으로 나오게 됩니다.
이제 여기에 설정자의 접근수준이 추가된 예시를 보겠습니다.
사실 이 코드에서는 접근수준이 아무 .. 효과(?)가 없습니다. 왜냐면 오류날법한 코드는 다 빼놔서.. 사실 의미가 없음
public struct SomeType {
private var count: Int = 0
public var publicStoredProperty: Int = 0
public private(set) var publicGetOnlyStoredProperty: Int = 0
internal var internalComputedProperty: Int {
get {
return count
}
set {
count += 1
}
}
internal private(set) var internalGetOnlyComputedProperty: Int {
get {
return count
}
set {
count += 1
}
}
public subscript() -> Int {
get {
return count
}
set {
count += 1
}
}
public internal(set) subscript(some: Int) -> Int {
get {
return count * some
}
set {
count = some
}
}
}
var someInstance: SomeType = SomeType()
print(someInstance.internalComputedProperty) //0
someInstance.internalComputedProperty = 100
print(someInstance.internalComputedProperty) //1
print(someInstance[]) //1
someInstance[] = 100
print(someInstance) //SomeType(count: 2, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
print(someInstance[], someInstance[10], someInstance[100]) //2 20 200
someInstance[100] = 1
print(someInstance) //SomeType(count: 100, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
이 코드의 출력값은
0
1
1
SomeType(count: 2, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
2 20 200
SomeType(count: 100, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
이렇게 됩니다.
조,,금,, 복잡하게 보일 수 있지만 출력값 하나씩 보겠습니다.
우선
print(someInstance.internalComputedProperty) // 0
internalComputedProperty는 getter 에서 count 값을 돌려보내주고 있기 때문에
초기값인 0을 보내주고 있습니다 -> 이해 완.
두 번째,
someInstance.internalComputedProperty = 100
print(someInstance.internalComputedProperty) //1
그 다음, internalComputedProperty에 100을 줬는데요.
이러면 internalComputedProperty의 setter가 동작합니다.
setter에서는 count+=1 을 하고 있죠. 준 값이 100이든 999든 9999든 관심없고 count만 1 올려주면 됩니다.
100, 999, 9999, 어쩌구 값은 날아가게 됩니다(?)
그래서 다시 internalComputedProperty를 print 했을 때는
0에서
100이라는 숫자를 이용해서 setter 접근 -> count+=1 됨
따라서 1 출력
여기까지 이해하셨을까요 ?
다음,
print(someInstance[]) //1
struct에 []를 붙임 = struct의 subscript를 부름.
이렇게 사고가 흘러가야합니다. 배열이라고 자꾸 생각하지말고 그냥 subscript를 부르려면 []를 써야한다고 생각해!!
그래서 someInstance에 []를 붙임으로서 someInstance의 subscript가 불려집니다.
근데 이 SomeType의 subscript에는 두 종류가 있는데요.
하나는 그냥,
하나는 some이라는 이름으로 Int값이 하나 더 들어오는 subscript
얘는 추가적인 Int값을 [] 사이에 넣어주지 않았으므로 위 코드의 그냥 subscript() -> Int 가 불리게 됩니다.
그리고 그 subscript는 count를 리턴해주기로 되어있죠.
그래서 출력값이 아까 count값 그대로인 1이 되게 됩니다.
그리고 다음,
someInstance[] = 100
print(someInstance) //SomeType(count: 2, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
someInstance[] = 100
이 말은 즉슨
someInstance[] : someInstance의 subscript의
= 100 : 100을 들고 setter를 부를게
라는 말로,
setter에 가면 근데. 또 단순히 count+=1 만 합니다. 그래서 다시 100은 그냥 날라가고
count는 2가 되죠.
그렇게 하고 현재 someInstance를 출력해보면
SomeType(count:2, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0) 이라는 구조체 형태임을 알 수 있게 됩니다.
print(someInstance[], someInstance[10], someInstance[100]) //2 20 200
얘도 볼게요.
얘는 셋 다 []가 붙어있네요. --> subscript 부름
첫 번째는 아까 설명한 것처럼 추가적인 Int값을 [] 사이에 넣어주지 않았으므로 위 코드의 그냥 subscript() -> Int 가 불리게 됩니다.
단순히 return count 즉, 2가 나오겠죠.
두 번째는 [] 사이에 10이라는 Int를 전달해줬습니다. 따라서 subscript() -> Int가 아닌!!
subscript(some: Int) -> Int 얘가 불리게 됩니다. 그리고 10이라는 숫자는 자연히 some이라는 이름으로 getter에 들어가겠죠.
getter를 보면 return count * some 으로 2*10 = 20이라는 Int값이 나오게 됩니다.
세 번째도 같은 맥락으로 some=100, count*some = 2*100 = 200
이 출력됩니다.
이제..마지막...
someInstance[100] = 1
print(someInstance) //SomeType(count: 100, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
someInstance[100] = 1
이 말을 해석해보겠습니다.
someInstance[100] : somInstance의 subscript(some: Int) -> Int 얘를 부를게. 그리고 some은 100이야
= 1 : 1이라는 숫자를 들고 setter로 갈게
setter로 갑니다.
그랬더니 count = some 이라고 하네요. 그러면 이제 count는 some = 100 이 됩니다.
들고간 1이라는 숫자는 ? 전혀 상관이 없게 되죠. 왜냐? 1을 쓰겠다고 안 했으니까. 우선 "들고" setter로 가봤더니 안 씀. 그냥 단순히 그런거임.
그래서 print(someInstance) 로 내 사고가 맞는지 확인해보았더니
SomeType(count: 100, publicStoredProperty: 0, publicGetOnlyStoredProperty: 0)
짠.
count가 100이 된 모습으로 반겨주고 있었습니다..
그럼 끝!!
'iOS' 카테고리의 다른 글
모나드 Monad in swift (1) | 2023.09.04 |
---|---|
제네릭과 표현 패턴 Generics and Expression Pattern 활용 예시 (0) | 2023.03.30 |
reduce, map의 조합 그리고 CaseIterable의 allCases in Swift (0) | 2023.01.12 |
prepareForReuse() 의 사용법 / 쓰는 이유 (0) | 2022.02.22 |
Delegate Pattern 서로 다른 클래스에 접근하기 / 동작하기 / 데이터 전달하기 (2) | 2021.07.13 |
- Total
- Today
- Yesterday
- subscript
- Objective-C
- 알림대화상자
- 어댑터
- 스낵바설정
- 터치리스너
- 다이얼연결
- allcases
- CaseIterable
- 표현패턴
- ios
- 프래그먼트
- 전화걸기연결
- 상태드로어블
- 부가데이터
- prepareforreuse
- swift
- 제스처디텍터
- 비트맵버튼
- 데이터
- objc
- 인플레이터
- 액션바
- 프래그먼트매니저
- 뷰페이저
- 페이저타이틀스트립
- 안드로이드
- 전화연결하기
- 쉐이프드로어블
- 카카오톡열기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |