이전에 다룬 구조체(Struct)의 주요한 특징을 기억하시나요?
참조 타입인 클래스(Class)와는 달리,
인스턴스 객체가 생성될 때 마다 별도의 값을 가지게 되는,
'값 타입(Value Type)'이란 부분이 구조체의 중요한 특징 중 하나였습니다.
그렇기 때문에 ~
클래스는 인스턴스 메서드를 활용해 내부 인스턴스 값을 변경할 수 있으나,
구조체는 '값' 자체를 복사하여 사용하므로 그렇지 못한다고 생각했지만...?
구조체의 성질을 '변화' 시켜서 내부 데이터 값을 수정할 수도 있습니다!
그 시작으로 mutable과 immutable이란 용어를 짚고 넘어가보도록 하겠습니다.
mutable과 immutable
구조체는 상수(Constant)와 동일한 변화되지 않는(Immutable) 성질이다.
mutating의 사전적 의미는 다음과 같습니다.
mutating
- '변화시키다' 혹은 '돌연변이'
말 그대로,
원래 그렇지 않은데 ➟ 조건에 따라 돌연변이가 되는 행위로도 해석되는데 말입니다..
근데, mutating이 대체 구조체와 무슨 연관이 있는걸까요?
mutable 하다, immutable 하다
- Swift 문법에 대한 학습 초기, 이미 mutable과 immutable에 대한 의미를 알아보았습니다.
- 바로 변수(var)와 상수(let)가 변화되는, 즉 'mutable'의 특징에 따라 구분됩니다.
- 이는 참조타입인 클래스와 값 타입인 구조체 또한 동일하게 적용됩니다.
- 클래스는 기본적으로 항상 'mutable' 하다고 볼 수 있습니다.
- 하지만, 구조체는 default 값으로 'immutable' 규칙을 지키게 됩니다.
구조체의 성질변화, mutating
- 구조체는 immutable 규칙을 지키는 동시에, mutable한 메서드를 사용할 수 있습니다.
- 기본적으로 구조체 인스턴스 메서드에서는 내부 값(Property)를 수정할 수 없습니다.
- 다만 'mutating' 키워드를 활용할 시 mutable한 성질을 가질 수 있습니다!
- 다음 예시코드는 mutating 키워드를 활용한 구조체 내부의 값을 변경하는 과정입니다.
- Animals란 구조체는 name 문자열과 age 정수값을 데이터로 가지고 있습니다.
- 동물의 나이를 5살로 유지하고 싶다는 생각에, 'defaultAge'란 인스턴스 메서드를 생성합니다.
// 예제 코드 (구조체 Animals)
struct Animals {
let name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func defaultAge() {
age = 5
}
}
- 하지만, immutable한 구조체의 성격에 따라 인스턴스 메서드에 아래와 같은 오류가 발생합니다.
- 이유는 즉, initializer 시 self 키워드 자체가 상수(let)로 정의되어 있기 때문입니다.
- 따라서 DefaultAge() 메서드는 작동할 수 없고, 앞서 언급한 mutating 키워드를 붙여야 합니다.
struct Animals {
let name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
// mutating 키워드를 인스턴스 메서드 앞에 붙인다.
mutating func defaultAge() {
age = 5
}
}
- myDog 인스턴스를 생성한 후, 초기값을 부여합니다.
- name은 'Coco', age는 10으로 설정한 이후, 내부에 위치한 defaultAge()를 호출한다면?
- age는 5로 변경되는 동시에, mutable한 성격을 가지게 됩니다.
var myDog: Animals = Animals(name: "Coco", age: 10)
myDog.defaultAge()
print(myDog.age) // 5
이번 포스팅에서 다룬 mutable이란 개념은
추후 SwiftUI View(구조체)를 다룰 시 연계되는 내용 중 하나이므로,
반드시 숙지하고 넘어갈 필요가 있겠습니다.
'iOS > Swift' 카테고리의 다른 글
[iOS/Swift] Extension(확장)을 통한 타입에 새로운 기능 부여하기 (0) | 2023.03.23 |
---|---|
[iOS/Swift] 타입에 의존하지 않는 범용코드, 제네릭(Generic) (0) | 2023.03.12 |
[iOS/Swift] 약속을 위한 청사진(Blueprint), 프로토콜(Protocol) (0) | 2023.03.05 |
[iOS/Swift] Swift에서의 구조체(Struct), 값 타입과 참조 타입의 비교 (0) | 2023.02.22 |
[iOS/Swift] 상속(Inheritance)을 통한 재 정의, 오버라이딩(Overriding) (0) | 2023.02.19 |
댓글