선행 포스팅
Swift 레퍼런스 중 Methods와 Subscripts 내용을 번역한 포스팅입니다.
자세한 개념 설명은 위 두 개의 포스팅에서 다루었고,
문서의 내용 중 몇 가지를 직접 실습해보겠습니다.
mutating 실습
mutating 키워드는 구조체나 열거형에서만 사용 가능합니다.
class에서 mutating을 쓰면 컴파일 에러가 발생해요.
원래 구조체나 열거형의 메서드 안에서 자신의 프로퍼티를 수정할 수 없습니다.
만약 수정을 시도하면
이렇게 mutable 하지 않다는 에러가 뜹니다.
에러를 펼쳐보면
mutable하게 만들라고 하면서 Fix 를 지원하는데요.
여기서 Fix를 누르면
struct SomeClass {
var value: Int = 0
mutating func increase() {
value += 1
}
}
func 앞에 mutating 키워드가 붙으면서 mutable 해집니다.
mutating이라고 해서 호출이 달라지거나 그러진 않습니다.
var someClass: SomeClass = SomeClass()
print(someClass.value) //0
someClass.increase()
print(someClass.value) //1
평범하죠?
하지만 let 인스턴스에서는 mutating 메서드를 호출하지 못합니다.
mutating 메서드는 기본적으로 프로퍼티를 변경한다는 개념이 내포되어 있습니다.
그래서 아래처럼 실제로는 변경을 하지 않더라도 변경할 위험이 있기 때문에 컴파일 타임에 막는거에요.
struct SomeClass {
var value: Int = 0
mutating func increase() {
}
}
let someClass: SomeClass = SomeClass()
someClass.increase() //에러
mutating 키워드를 붙인다는 것 자체가 "나는 프로퍼티를 변경하겠다."라는 의도를 품은 것이므로,
이 의도 자체가 불순해서(?) 컴파일 에러가 발생하는거죠.
그래서 mutating 키워드는 반드시 프로퍼티를 수정할 목적으로만 사용해야 합니다.
mutating with enum
mutating을 enum에서 사용하는 것도 너무 인상적이었습니다.
enum StateSwitch {
case off, low, high
mutating func next() {
switch self {
case .off:
self = .low
case .low:
self = .high
case .high:
self = .off
}
}
}
var stateSwitch = StateSwitch.off
print(stateSwitch) //off
stateSwitch.next()
print(stateSwitch) //low
예시부터 너무 실용적으로 보입니다.
원래였다면 여러 상태를 배열에 넣어서 count 변수를 이용해 하나씩 이동했을텐데요.
enum에 mutating 키워드를 접목함으로서 직관적이고 깔끔하게 코드가 작성되네요.
Subscripts 실습
이번 Subscripts을 공부하기 전까지는 Subscripts에 대해 자세히 몰랐습니다.
단순히 콜렉션이나 리스트에서 사용할 수 있는 [ ] 라고만 알고 있었는데요.
이를 직접 정의하여 사용할 수 있다는 게 새로운 정보였어요.
자세한 Subscripts 내용은 맨 위의 Subscripts 글 링크에서 보시면 좋을 거 같고,
이번 포스팅에서는 간단히 알아본 후 직접 실습해보도록 합시다.
우리가 익숙한 서브스크립트는 이런 코드죠?
var array: [Int] = [1, 2, 3]
print(array[0]) // 1
여기에서 0을 감싸는 [ ]가 바로 서브스크립트입니다.
Array 정의에 들어가 확인해보면
subscript가 이렇게 정의되어 있습니다.
직접 한 번 subscript를 구현해볼텐데요
제가 가장 흥미로웠던 활용 방법은 String 이었습니다.
String은 다른 언어처럼 [index]로 String 사용이 불가능합니다.
String에서 []를 하면
String.Index를 사용하라고 에러가 납니다.
그렇지만 서브스크립트를 이용하면 가능하더라고요.
extension String {
subscript(idx: Int) -> String? {
guard idx >= 0 && idx < count else { return nil }
let target = index(startIndex, offsetBy: idx)
return String(self[target])
}
}
String[ ] 안에 Int를 인자로 넘기면 그 Index가 범위 내에 있다면 옵셔널 String 형을 반환합니다.
var test: String = "HI"
print(test[0]) //Optional("H")
print(test[-1]) //nil
print(test[10]) //nil
이것처럼 범위 내라면 해당 index의 문자열을 반환해줘요.
이것만으로도 엄청난데? 왜 지금까지 이런걸 몰랐지? 싶었습니다.
이제 mutating과 subscript... 활용해야겠죠?
감사합니다!
참고
https://babbab2.tistory.com/123?category=828998
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.