initialization 톺아보기(2) — 클래스 초기화

kangYundol
daily-monster
Published in
6 min readApr 13, 2024

initialization 톺아보기(1) — 값 타입 초기화
initialization 톺아보기(2) — 클래스 초기화
initialization 톺아보기(3) — 2단계 초기화와 클래스 상속

안녕하세요 토요일 윤돌이입니다-! 오늘은 initialization의 두번째 내용으로 클래스 초기화에 대해 이야기하려고 해요.

원래는 클래스 초기화의 모든 내용을 정리하려 했으나 토요일이 얼마 남지 않은 관계로ㅎㅎ ,, 클래스 초기화의 절반 내용만 들고왔습니다!

오늘은

  1. designated initializer와 convenience initialzer
  2. 클래스 타입에서의 초기화 위임

이 두 가지 내용을 다뤄보겠습니다.

지난 포스팅에서 구조체와 클래스는 초기화 시점에 모든 저장 프로퍼티가 초기값을 가지고 있어야한다고 했습니다!

지난 글에서 정리한 초기화하는 방법으로는

  1. 프로퍼티를 선언할 때 초기값을 지정하기
  2. 프로퍼티 타입을 옵셔널로 주기

이 두가지가 있었습니다.

만약 하나의 프로퍼티라도 이 두 가지 조건 중 하나를 만족하지 않는 경우에는 어떻게 될까요?

클래스는 구조체와 다르게 memberwise initiailizer가 없어서 반드시 init 구문이 필요합니다. 또한 클래스는 상속이 가능하기 때문에 상속받은 부모 클래스의 프로퍼티까지 모두 초기화해줘야 해요.

클래스는 모든 저장 프로퍼티가 초기값을 가질 수 있도록 두 가지 초기화 구문을 정의하고 있습니다.

  1. Designated initializer(지정된 초기화 구문)
  2. Convenience Initializer(편의 초기화 구문)

designated initializer와 convenience initializer

designated initializer

designated initializer는 클래스가 주로 사용하는 초기화 구문입니다. 저희가 클래스 만들 때 항상 사용하는 init() 이 바로 designated initializer입니다!!

designated initializer는 반드시 슈퍼 클래스의 init을 호출해주어야 해요.

상속받은 클래스가 있다면 슈퍼 클래스의 프로퍼티까지 모두 초기화해주어야 하기 때문이에요.

클래스는 최소 하나 이상의 designated initiailizer를 제공합니다.

init(<#parameters#>) {
<#statements#>
}

convenience initializer

convenience initializer는 보조 초기화입니다. 보조라는 이름이 붙은만큼 이 초기화구문은 필수가 아니예요.

convenience init(<#parameters#>) {
<#statements#>
}

designated initializer를 도와주는 역할이기 때문에 designated initializer의 파라미터 중 원하는 값을 기본값으로 설정해서 도와주는 역할을 합니다.

convenience 생성자는 다음과 같은 특징을 가지고 있어요.

  1. convenience 생성자는 슈퍼 클래스의 생성자를 직접 호출할 수는 없습니다.
  2. 같은 클래스 내에 있는 convenience 생성자나 designated 생성자를 호출해야합니다.
  3. ⭐보조하는 역할이기 때문에 최종적으로는 designated initializer를 반드시 호출해주어야 합니다!

convenience initailizer를 사용하더라도 최종적으로는 designated initializer를 호출하기 때문에 클래스 내 모든 프로퍼티가 초기화가 가능해지는 것이죠!

Initializer Delegation for Class Types

지금까지 내용을 정리하자면 아래와 같습니다.

  1. designated initiailizer는 슈퍼 클래스의 초기화 구문을 호출해야 한다.
  2. convenience 초기화 구문은 같은 클래스에 있는 다른 init 구문만 호출 가능하다.
  3. convenience 초기화는 결국 designated initiailizer를 호출하게 되어있다!

이 내용을 그림으로 표현한 것입니다. 그림으로 보니 이해가 더 쉽네요!

이 그림을 코드로 나타내볼까요?

class Machine {
var owner: String
var color: String

init(owner: String, color: String) {
self.owner = owner
self.color = color
}

convenience init(owner: String) {
self.init(owner: owner, color: "Silver")
}

convenience init() {
self.init(owner: "Yundol")
}
}
class Computer: Machine {
var osType: String
var usedYear: Int

init(osType: String, usedYear: Int) {
self.osType = osType
self.usedYear = usedYear
super.init(owner: "Yundol", color: "Black")
}

init(usedYear: Int) {
self.osType = "iOS"
self.usedYear = usedYear
super.init(owner: "YundolE", color: "White")
}

convenience init(osType: String) {
self.init(osType: osType, usedYear: 0)
}

여기서 주의할 점은 convenience init은 designated init과 파라미터가 완전히 같으면 안됩니다! 보조해주는 역할인데 이미 같은 init이 있으면 사용할 이유가 없으니까요!

1, 2, 3번 규칙만 만족한다면 이렇게 복잡한 구조의 initializer 관계도 가질 수 있습니다.

오늘은 클래스의 초기화 구문인 designated initializer와 convenience initializer 그리고 클래스 내 초기화 구문 위임에 대해 일부 살펴보았습니다!!

다음 글에서는 클래스 초기화의 나머지 내용에 대해 알아보아요 ~

https://bbiguduk.gitbook.io/swift/language-guide-1/initialization#initializer-delegation-for-class-types

--

--