티스토리 뷰
Class 와 Struct에 대한 궁금증이 생겼다. 두 가지를 무턱대고 사용했고 당연히 ViewController를 만들 때는 Class, Test Model를 만들 때는 Struct로 Model를 만들었다. 이유는 크게 없었고 그냥 그렇게 배웠고 그렇게 만들어 왔기 때문에. 어떤 언어를 배우던지 Class, Struct는 큰 차이가 없다고 말하는데 그 미묘한 차이는 뭔지 왜 말을 안해주는지.. 그래서 검색을 해보았다.
🙏 공통점
- 프로퍼티와 메서드를 구조화해서 묶어둔 형식
- 하나의 사용자 지정 타입을 만드는 것
- 이니셜라이저 init 를 정의해서 초기 상태를 지정할 수 있음
- 새로운 기능 추가를 위해서 Extension 사용 가능
- Protocol 사용 가능
- 서브 스크립트 정의 가능
- 프로퍼티값에 접근하고 싶다면 . 를 사용
🤲 차이점
1. Struct
- 값(Value) Type
- Value 이기에 multi-thread 환경에서 공유 변수로 인한 문제를 일으킬 확률이 적다. - Stack memory 사용
- 속도가 빠르다.👍
- Complier의 메모리 할당/해제가 정확하다. - let 으로 초기화 이후에 값 변경이 불가능
2. Class
- 참조(Reference) Type
- 상속 가능
- 상속이 가능하기에 타입캐스팅도 허용된다. - deinitalize도 구현 가능
- Heap memory 사용
- 속도가 느리다.😅 - let 으로 초기화 이후 값 변경 가능
- class 인스턴스에 하나 이상 참조 가능
- 식별 연산자(===) 사용 가능
- 상수와 변수가 같은 인스턴스를 참조하고 있는지 비교하기 위해 식별 연산자를 사용
검색하면서 내가 궁금해했던 것보다 차이점이 미미하다고 생각했다. 그래서 파고들어간 것이initalization 부분이다.
📨 initalization(초기화)
init은 Struct, class선언과 동시에 프로퍼티에 초기값을 지정해준다. 명확한 initalizer이고 타입 추론이 가능하게 하며 사용 시에 코드를 짧고 간결하게 만들 수 있다. 모든 프로퍼티에 할당하지 않으면 에러가 발생한다.
Objective-C와 차이점이 있다면 Swift의 init은 값을 반환하지 않는다고 한다.
struct Model {
var name: String
var age: Int
init(age: Int){
name = "test"
self.age = age
}
}
let firstModel = Model(age: 10)
1. Struct
1. 자동 생성
- 기본 이니셜라이저(Default Initalizers)
- stored property의 초기값을 사용함
- stored property를 모두 초기화한 경우에만 사용 가능(옵셔널 아님)
struct Model {
var name: String = "Tom"
var age: Int = 10
}
let model = Model()
해당 코드처럼 property를 모두 초기화시킨 경우만 기본 이니셜라이저 사용 가능하다.
- 멤버와이즈 이니셜라이저(Memberwise Initalizers)
- 자동으로 stored property가 가진 값을 사용
- stored property가 하나라도 초기화되지 않은 경우 사용
- 사용자 지정 이니셜라이저를 정의하지 않았다면 멤버와이즈 이니셜라이저를 제공
struct Model {
var name: String
var age: Int
}
let model = Model(name: "Tom", age: 10)
2. 사용자 지정(Customizing Initalizers)
사용자 지정 이니셜라이저는 자동 생성 이니셜라이저와 함께 사용할 수 없다.
만약, 두 가지를 모두 사용하고 싶다면 extension를 이용하면 가능하다.
struct Model { // optional 사용해서 실패할 경우 nil반환
var name: String?
var age: Int?
init(name: String) {
self.name = name
age = 10
}
}
let model = Model(name: "Tom") // name: "Tom", age: 10
사용자가 직접 init 매개변수를 지정해서 초기화 함수를 만들 수 있다. 내부에 있는 매개변수의 조합만 서로 다르다면 init를 여러개로 만들 수도 있다. 또한, 내부 내용도 사용자가 직접 지정 가능하다.
- Delegate Initalizers (<-> class와 동작 방식에 차이 존재)
- init 안에서 self.init() call
- 다른 init에 초기화를 위임해서 코드 중복을 예방
struct Model {
var name: String?
var age: Int?
init(name: String, age: Int) {
self.name = name
self.age = age
}
init(name: String) {
self.init(name, 10)
}
}
let model = Model(name: "Tom") // name: "Tom", age: 10
2. Class
모든 클래스의 stored property와 superclass로부터 상속받은 모든 property는 초기화 단계에서 반드시 초기값이 할당되어야 한다.
1. 지정 이니셜라이저(Designated Initalizers)
- 모든 stored property 초기화
- 반드시 한 개 이상의 Designated Initalizers 필요
- superclass Initalizer call -> 연쇄로 superclass call
- 자신이 superclass인 경우에는 super.init()하지 않아도 된다.
2. 컨비니언스 이니셜라이저(Convenience Initalizers)
- 있어도 되고 없어도 되는 이니셜라이저
- 매개변수를 지정 이니셜라이저와 다르게 받아서 지정 이니셜라이저를 호출해서 초기화
- 무조건! self.init() 사용
- 무조건! 편의 이니셜라이저는 지정 이니셜라이저를 호출 - super.init() , superclass func 초기화하기위해 호출 불가능
- 시간 단축 및 class Initalizers의 의도를 명확하게 해줌
class Model {
var name: String?
// 지정 이니셜라이저
init(name: String){
self.name = name
}
}
class SubModel: Model {
var age: Int
// superclass를 상속받은 지정 이니셜라이저
init(name: String, age: Int) {
self.age = age
super.init(name: name)
}
// 편의 이니셜라이저
convenience init(age: Int) {
self.init(name: "Tom", age: age)
}
}
Designated Initalizers는 항상 superclass를 Delegate
convenience Initalizers는 항상 같은 class를 Delegate
잘못 초기화하는 상황을 막기 위해서 자식 클래스가 부모 클래스의 init를 꼭 상속하게 하지 않는다.
but, 특정 조건을 만족하면 부모 클래스의 init를 상속해야 함.
- 자식이 지정 Initalizers를 정의하지 않았을 경우 -> 부모 클래스 지정 init 상속
- 자식이 부모의 지정 Initalizers를 모두 구현했을 경우 -> 부모 클래스 편의 init 상속
3. 필수 이니셜라이저(Required Initalizers)
- superclass에서 선언하면 자식 클래스는 무조건 필수 이니셜라이저를 구현
- 따로 override하지 않아도 됨
struct Model {
required init() {
...
}
}
struct SubModel: Model {
required init() {
...
}
}
4. 클로져 이니셜라이저(Closure Initalizers)
- struct도 사용 가능
- 다소 복잡한 값을 할당할 때 사용하기 좋음
- 한 번만 호출되며, 변수var일 경우에는 값 변경도 가능
- stored property에 사용자 정의나 설정이 필요하다면, 사용자 정의 기본 값을 제공하기 위한 클로저나 전역 함수를 사용
struct Model {
let age: [Int] = {
var myAge: [Int] = []
for i in 1...10 {
myAge.append(i)
}
return myAge
}
}
🤔 Struct? Class?
- 간단한 값의 집합을 캡슐화 시킬 수 있다. -> struct
- 캡슐화한 값에 reference보다 copy가 더 합당할 때 -> struct
- property가 value type이여야 할 때 -> struct
- 상속받거나 상속할 필요가 있을 때 -> class
- deinit 사용 -> class
☑️ Plus
Value type :
Struct, Enum, Tuple
struct String, struct Array( Set, Dictionary)
Reference type :
Class,Function
잘못된 점과 피드백은 댓글로 주시면 감사하겠습니다.
참고:
https://medium.com/@jgj455/%EC%98%A4%EB%8A%98%EC%9D%98-swift-%EC%83%81%EC%8B%9D-struct-class-60fa5fd2218d
https://jusung.gitbook.io/the-swift-language-guide/language-guide/14-initialization
https://stackoverflow.com/questions/24217586/structure-vs-class-in-swift-language
'Swift' 카테고리의 다른 글
[Swift] Property (0) | 2021.02.21 |
---|---|
[Swift] Enum (0) | 2021.02.20 |