아요 개발 일기
[Swift] 생성자(initializer) 본문
생성자란?
- 인스턴스가 생성될 때의 형식과 할 일을 정의한다고 하여 생성자라고 부릅니다.
- 클래스가 객체화 될 때 자동으로 실행되는 메소드를 지칭합니다. ( 객체의 인스턴스를 만드는 메소드)
- 스위프트 초기화 혹은 생성자는 init 이라는 키워드의 메소드가 담당합니다.
- init은 구조체와 클래스 모두에서 지원되는 기능입니다.
- 일반 메소드 정의와 다르게 func 라는 키워드가 필요 없습니다.
생성자는 init() 형태로 작성되며, 필요하면 argument를 추가해서 작성할 수도 있습니다.
초기화 메소드 init() 형식
init(<매개변수> : <타입>, <매개변수> : <타입>, ... ) {
1. 매개변수의 초기화
2. 인스턴스 생성 시 기타 처리할 내용
}
초기화 구문 = 초기화 메소드
초기화 메소드는 대표적인 특성이 아래와 같이 있습니다.
- 초기화 메소드의 이름은 init으로 통일된다
- 매개변수의 개수, 이름, 타입은 임의로 정의할 수 있다. ( 인스턴스 생성 과정에서 넣어야 하는 인자값의 순서와 형식이 결정)
- 매개변수의 이름과 개수, 타입이 서로 다른 여러 개의 초기화 메소드를 정의할 수 있다. ( 메소드의 일종이므로 오버라이딩할 수 있음)
- 정의된 초기화 메소드는 직접 호출되기도 하지만, 대부분 인스턴스 생성 시 간접적으로 호출된다.
초기화 메소드의 정의 방법과 호출 방법을 코드로 살펴 볼까요?
struct Resolution {
var width = 0
var height = 0
// 초기화 메소드 : Width를 인자값으로 받음
init(width: Int) {
self.width = width
}
}
class VideoMode {
var resolution = Resolution(width: 2048)
var interlaced = false
var frameRate = 0.0
var name: String?
// 초기화 메소드 : interlaced, frameRate 두 개의 인자값을 받음
init(interlaced: Bool, frameRate: Double) {
self.interlaced = interlaced
self.frameRate = frameRate
}
}
먼저, width초기화 메소드가 정의되어있는 Resolution 구조체와
interlaced,frameRate 초기화 메소드가 정의되어있는 VideoMode 클래스를 정의 하였습니다.
이제 각각의 인스턴스를 생성해 볼까요?
방법 1
// Resolution 구조체에 대한 인스턴스 생성
let resolution = Resolution.init(width: 4096)
// VideoMode 클래스에 대한 인스턴스를 생성
let videoMode = VideoMode.init(interlaced: true, frameRate: 40.0)
방법 2
// Resolution 구조체에 대한 인스턴스를 생성
let resolution = Resolution(width: 4096)
// VideoMode 클래스에 대한 인스턴스를 생성
let videoMode = videoMode(interlaced: true, frameRate: 40.0)
방법1 처럼 init 메소드를 호출해 주는 방법이 있지만, 방법2와 같이 init을 생략한 후 호출도 가능합니다.
아래 코드는 서로 다른 여러 개의 init 메소드를 정의하고 호출 및 할당하는 예시 입니다.
class VideoMode {
var resolution = Resolution(width: 4096)
var interlaced = false
var frameRate = 0.0
var name: String?
// 초기화될 때 name 인자값만 받는 init 구문
init(name: String) {
self.name = name
}
// 초기화될 때 interlaced 인자값만 받는 init 구문
init(interlaced: Bool) {
self.interlaced = interlaced
}
// 초기화될 때 interlace, frameRate 두 개의 인자값을 받는 init 구문
init(interlaced: Bool, frameRate: Double) {
self.interlaced = interlaced
self.frameRate = frameRate
}
// 초기화될 때 interlace, frameRate, name 세 개의 인자값을 박는 Init rnans
init(interlaced: Bool, frameRate: Double, name: String) {
self.interlaced = interlaced
self.frameRate = frameRate
self.name = name
}
}
// VideoMode 클래스에 대한 인스턴스를 생성하고 상수에 할당
let nameVideoMode = VideoMode(name: "홍길동")
let simpleVideoMode = VideoMode(interlaced: true)
let doubleVideoMode = VideoMode(interlaced: true, frameRate: 40.0)
let tripleVideoMode = VideoMode(interlaced: true, frameRate: 40.0, name: "홍길동")
init 코드를 작성하고나면, 아래 코드와 같이 기본 초기화 구문은 제공되지 않습니다.
class VideoMode {
var resolution = Resolution(width: 4096)
var interlaced = false
var frameRate = 0.0
var name: String?
// 초기화 메소드 : interlaced, frameRate 두 개의 인자값을 받음
init(name: String) {
self.name = name
}
}
//VideoMode 클래스에 대한 인스턴스를 생성하고 상수에 할당
let defaultVideoMode = VideoMode() // Error
let nameVideoMode = VideoMode(name: "홍길동")
그럼 기본 초기화 구문을 사용할 수 없는건가요??
사용 할 수 있습니다. 하지만, 아래와 코드와 같이 기본 init() 메소드를 꼭 정의해주어야 합니다.
class VideoMode {
var resolution = Resolution(width: 4096)
var interlaced = false
var frameRate = 0.0
var name: String?
// 기본 초기화 구문
init() {
}
// 초기화 메소드 : interlaced, frameRate 두 개의 인자값을 받음
init(name: String) {
self.name = name
}
}
//VideoMode 클래스에 대한 인스턴스를 생성하고 상수에 할당
let defaultVideoMode = VideoMode()
let nameVideoMode = VideoMode(name: "홍길동")
생성자
2-phase Initialization
클래스 생성시 두가지 단계
1. 모든 저장 프로퍼티는 모두 이니셜라이저 되야한다
—> 자식 프로퍼티부터 이니셜라이저해야한다
2. 부모 클래스까지 다 이니셜라이저하고나서야 프로퍼티를 사용 가능하다
—> 프로퍼티를 다 셋팅을하고나서 메소드를 사용할 수 있음
이런 규칙이 아주 중요함
규칙이 없다면?
프로퍼티가 셋팅도 안된 상태에서 인스턴스 메소드를 호출하게되고, 이렇게되면 우리가 원하는데로 동작하지 않고 버그가 생기게 됨
designated(주) vs convenience(부)
DI는 자신의 부모의 DI를 호출해야함
CI는 같은 클래스의 이니셜라이저를 꼭 하나 호출해야함
CI는 궁극적으로는 DI를 호출해야함
'Swift' 카테고리의 다른 글
[Swift] Split과 Components (0) | 2023.01.29 |
---|---|
[Swift] Method 랑 Computed Property 중 어떤걸 사용해야할까? (0) | 2023.01.29 |
[Swift] Method (메소드) (0) | 2023.01.29 |
[Swift] Diffable Datasource와 Compositional Layout (1) | 2023.01.29 |
[Swift] Weak, Strong Reference (feat. ARC) (0) | 2023.01.29 |