convenience init.. required init 등 제대로 알고 쓰자 싶어서 쓰는 글
클래스에서는 지정 이니셜라이저와 편의 이니셜라이저로 두 종류의 이니셜라이저가 존재한다.
그리고 상속이라는 클래스의 특성 때문에 다양한 패턴의 이니셜라이저가 생길 수 있다.
기본적인 이니셜라이저보다는 조금 심화된 내용인 클래스 이니셜라이저에 대해 살펴보자
지정 이니셜라이저(Designated Initializer)
- 클래스의 주요 이니셜라이저
- 필요에 따라 부모 클래스의 이니셜라이저를 호출할 수 있으며, 이니셜라이저가 정의된 클래스의 모든 프로퍼티를 초기화해야 하는 임무를 갖고 있음
- 한 개 이상 정의해야 함
- 조상 클래스에서 지정 이니셜라이저가 자손 클래스의 지정 이니셜라이저 역할을 충분히 할 수 있다면, 자손 클래스는 지정 이니셜라이저를 갖지 않을 수도 있다. (자손 클래스가 옵셔널 저장 프로퍼티 외에 다른 저장 프로퍼티가 없을 가능성이 큼)
편의 이니셜라이저(Convenience Initializer)
- 초기화를 좀 더 쉽게 도와주는 역할
- 내부에서 지정 이니셜라이저를 호출함
- 지정 이니셜라이저와 달리 필수 요소는 아님
- 지정 이니셜라이저의 매개변수가 많아 외부에서 일일이 전달 인자를 전달하기 어렵거나 특정 목적을 위해 사용
지정 이니셜라이저는 아래와 같은 형식으로 정의할 수 있다.
init(매개변수들) {
// 초기화 구문
}
편의 이니셜라이저는 앞에 convenience 지정자를 init 키워드 앞에 명시해주면 된다.
convenience init(매개변수들) {
// 초기화 구문
}
지정 이니셜라이저와 편의 이니셜라이저 사이의 관계를 간단히 정리해 보자면
- 자식 클래스의 지정 이니셜라이저는 부모 클래스의 지정 이니셜라이저를 반드시 호출해야 함
- 편의 이니셜라이저는 자신을 정의한 클래스의 다른 이니셜라이저를 반드시 호출해야 함
- 편의 이니셜라이저는 궁극적으로 지정 이니셜라이저를 반드시 호출해야 함
그렇다면 실제로 클래스 초기화는 어떻게 진행되는 것일까?
클래스 초기화는 총 2단계를 거친다.
1단계
- 클래스가 지정 또는 편의 이니셜라이저를 호출함
- 그 클래스의 새로운 인스턴스를 위한 메모리가 할당된다. (여기서 메모리는 아직 초기화되지 않은 상태)
- 지정 이니셜라이저는 클래스에 정의된 모든 저장 프로퍼티에 값이 있는지 확인한다. (현재 클래스 부분까지의 저장 프로퍼티를 위한 메모리는 이제 초기화됨)
- 지정 이니셜라이저는 부모 클래스의 이니셜라이저가 같은 동작을 행할 수 있도록 초기화를 양도함
- 부모 클래스는 상속 체인을 따라 최상위 클래스에 도달할 때까지 이 작업을 반복
최상위 클래스에 도달했을 때, 최상위 클래스까지의 모든 저장 프로퍼티에 값이 있다고 확인하면 해당 인스턴스의 메모리는 모두 초기화된 것이다. 이로써 1단계가 완료되는 것

2단계
- 최상위 클래스로부터 최하위 클래스까지 상속 체인을 따라 내려오면서 지정 이니셜라이저들이 인스턴스를 제각각 사용자 정의하게 된다. 이 단계에서는 self를 통해 프로퍼티 값을 수정할 수 있고, 인스턴스 메서드를 호출하는 등의 작업을 진행할 수 있다.
- 마지막으로 각각의 편의 이니셜라이저를 통해 self를 통한 사용자 정의 작업을 진행할 수 있음

글이 길어져 2편으로 나눠서 포스팅해야겠다.
다음 글에서는 이니셜라이저의 상속에 관해 다뤄볼 것이다.

'Study > Swift' 카테고리의 다른 글
[Swift] 고차함수(1) - map, flatMap, compactMap (0) | 2022.09.18 |
---|---|
[Swift] RunLoop.Mode (0) | 2022.08.01 |
[Swift] Run Loop (0) | 2022.07.25 |
[Swift] Initializer 심화 (2) (0) | 2022.07.20 |
[Swift] Property (0) | 2022.07.10 |