아요 개발 일기
[Swift] Struct - 구조체 본문
Struct
- C 언어 구조체 용도와 비슷하지만, 추가로 멤버 변수(프로퍼티), 함수(메소드) 정의 가능
- 상속이 불가능
- 확장(extention) 등 기능 사용 가능
- 값 타입 (= Value Type)
- Swift의 대부분의 큰 뼈대는 모두 구조체로 구성
- 메모리의 Stack 영역에 존재
값 타입이 뭐에요?
값 타입이란, 데이터의 크기가 고정적이기 때문에 메모리 스택에 생성되는 것을 말 합니다.
- 선언 : 선언만 하면 스택에 즉시 생성되므로 선언 직후부터 데이터를 저장하는 용도로 사용할 수 있습니다.
- 종료 : 더 이상 참조하는 변수가 없을 때 가비지 컬렉터에 의해 파괴됩니다.
- 데이터 : 복사에 의해 완전한 별개의 사본이 생성 되며 복사 후 사본과 원본은 별개의 변수 입니다. 즉, 완전히 다른 두 개의 변수가 생성되는 것을 말 합니다.
Stack에 대해 자세히 알고 싶은 분들은 메모리 구조 (feat.Stack과 Heap)포스팅을 참고해주세요!
정의 및 구현
struct 선언 후 이름만 선언하면되는 쉬운 코드니 어려움은 없죠?
struct 구조체 이름 {
...
}
그냥 정의 부분만 보면 이해가 어려우니 구현 부분도 함께 보도록 하겠습니다!
struct Student {
var name : String = "unknown"
var `class`: String = "Swift"
static func selfIntroduce() {
print("학생타입입니다")
}
func selfIntroduce() {
print("저는 \(self.class)반 \(name)입니다.")
}
}
Student 구조체를 만들고 안에 객체와 함수들을 선언하였습니다.
근데 코드를 보면 변수명이 `class`인 부분이 눈에 띄죠??? 먼저 선언한 변수 name과 달리 ``로 묶여있는데 왜 일까요?
스위프트에서는 예약어나 키워드로 등록되어 있는 단어는 변수나 상수명에 사용할 수 없습니다. class는 저희가 클래스를 정의할때 사용하는 키워드죠???? 그럼 변수명으로 사용이 불가능합니다..
그치만! 아래 설명과 같이 사용하면 예약어나 키워드를 변수명으로 사용할 수 있습니다.
Class, Enum 등으로 예약어를 대소문자를 바꾸거나 ``로 묶으면 변수 명으로도 사용가능하죠! (근데 되도록이면 예약어나 키워드는 변수명으로 사용하지 않는게 좋아요)
인스턴스를 생성하여 구조체를 활용해볼까요?
struct Student {
var name : String = "unknown"
var `class`: String = "Swift"
static func selfIntroduce() {
print("학생타입입니다")
}
func selfIntroduce() {
print("저는 \(self.class)반 \(name)입니다.")
}
}
Student.selfIntroduce() //학생 타입 입니다.
var yegom: Student = Student()
yegom.name = "yegom"
yegom.class = "스위프트"
yegom.selfIntroduce() //저는 스위프트반 yegom입니다.
let jina:Student = Student()
//불변 인스턴스이므로 프로퍼티 값 변경 불가
//컴파일 오류 발생
//jin.name = "jina"
jina.selfIntroduce()//저는 Swift반 unknown입니다.
yegom 이름으로 Student 구조체를 선언하였습니다.
`class` 객체는 인스턴스를 이용하여 불러올때 ``없이 class라고만 선언하는 것을 볼 수 있습니다.
아래 let으로 선언한 jina 인스턴스는 당연히 불변이니까 값을 바꾸려고 하면 오류가 발생하겠죠?
다른 예시 코드도 함께볼까요?
struct MyData {
var age:Int
var name:String
func getData() ->String {
return "[\(name)(\(age))]"
}
}
var data = MyData(age: 99, name: "Taro")
var data2 = data
data2.name = "Sojin"
data2.age = 24
print(data.getData()) // Taro(99)
print(data2.getData()) // Sojin(24)
위의 코드의 data 처럼 직접 변수 값들을 넣어주면서 인스턴스를 생성하는 것도 가능합니다.
구조체는 내부에서 데이터를 수정할때 꼭 사용해야하는 단어가 있는데요.
바로 Mutating func입니다. 아래 설명을 같이 볼까요?
Mutating function
Mutating function이란 구조체의 매서드가 구조체 내부에서 데이터를 수정할 때 선언하는 키워드입니다.
아래 코드를 보면서 이해해봅시다.
struct Point {
var x = 0
var y = 0
// 컴파일 에러남.
func moveTo(x: Int, y: Int) {
self.x = x
self.y = y
}
// 정상 실행
mutating func moveTo2(x: Int, y: Int) {
self.x = x
self.y = y
}
}
변수 x,y를 0으로 선언을 하였고, 그 값을 변경하려 합니다.
mutating을 선언하지 않고 내부 변수 값을 변경하면 위와 같이 컴파일 에러가 나게되니깐 꼭 붙여주세요!
음.. 구조체를 그럼 언제 사용해야하나요?
swift 언어 가이드에서 친절하게 아래 조건 중에 한가지 또는 그 이상 해당하는 경우에는 구조체를 사용하라고 기준을 제시해 주었습니다.
- 서로 연관된 몇 개의 기본 데이터 타입들을 캡슐화하여 묶는 것이 목적일 때
- 캡슐화된 데이터에 상속이 필요하지 않을 때
- 캡슐화된 데이터를 전달하거나 할당하는 과정에서 참조 방식보다는 값이 복사되는 것이 합리적일 때
- 캡슐화된 원본 데이터를 보존해야 할 때
Struct를 써야하는 경우
1. 두 object 를 “같다, 다르다”로 비교해야하는 경우
2. Copy된 각 객체들이 독립적인 상태를 가져야 하는 경우
3. 코드에서 오브젝트의 데이터를 여러 스레드 걸쳐 사용할 경우 (value 타입을 사용하면 각각의 객체이므로 오류 발상하지 않음)
'Swift > Grammar' 카테고리의 다른 글
[Swift] Enum - 열거형 (0) | 2023.01.29 |
---|---|
[Swift] 조건문 - Switch case (0) | 2023.01.29 |
[Swift] Class - 클래스 (0) | 2023.01.27 |
[Swift] 고차 함수 (0) | 2023.01.27 |
[Swift] 오류처리 (0) | 2023.01.27 |