chaneeii / iOS-Study-Log

✨ iOS에 대해 공부한 것들을 기록합니다 ✨
18 stars 0 forks source link

[Initializer 2탄] 클래스의 이니셜라이저 - 상속과 재정의 #32

Open chaneeii opened 1 year ago

chaneeii commented 1 year ago

클래스의 이니셜라이저 - 상속과 재정의

Intro

따라서,

=> 두종류의 이니셜라이저, 상속이라는 특성은 다양한 패턴의 이니셜라이저를 생기게 하고 이로인하여 클래스를 디자인할때 고민할 부분이 많다

클래스가 부모 클래스에서 상속한 모든 속성을 포함하여 모든 클래스의 저장 속성은 초기화 하는 동안 초기 값을 지정해줘야 한다.

1. 지정이니셜라이저(Designated Initializer)와 편의이니셜라이저(Convenience Initializer)

지정이니셜라이저

편의이니셜라이저

convenience 지정자를 init 앞에 명시하면된다.

convenience init(parameters) {
    statements
}

2. 클래스의 초기화 위임

지정 이니셜라이저와 편의 이니셜라이저의 관계를 간단히 정리해보기 위해 세 가지 규칙을 적용해 볼 수 있다.

  1. 자식클래스의 지정 이니셜라이저는 부모클래스의 지정 이니셜라이저를 반드시 호출해야 한다.
  2. 편의 이니셜라이저는 자신을 정의한 클래스의 다른 이니셜라이저를 반드시 호출해야 한다.
  3. 편의 이니셜라이저는 궁극적으로는 지정 이니셜라이저를 반드시 호출해야 한다.

이걸 기억하기 위해 간단히 정리하면,

위 규칙은 아래 그림으로 간단히 볼 수 있다. image

복잡한 클래스의 초기화 위임 규칙 모식도는 아래와 같다. image

3. 2단계 초기화 (Two-Phase initialization)

스위프트의 클래스 초기화는 2단계를 거친다.

1단계는 클래스에 정의한 각각의 저장 프로퍼티에 초깃값이 할당된다. 모든 저장 프로퍼티의 초기 상태가 결정되면 2단계로 돌입하여 저장 프로퍼티들을 사용자 정의할 기회를 얻습니다. 그 후 비로소 새로운 인스턴스를 사용할 준비가 끝납니다.

2단계 초기화를 해야하는 이유

Safety-Check (네단계 안전확인)

스위프트 컴파일러는 2단계 초기화를 오류없이 처리하기 위해 다음과 같은 네가지 안전확인을 실행한다.

  1. 자식클래스의 지정이니셜라이저가 부모클래스의 이니셜라이저를 호출하기 전에 자신의 프로퍼티를 모두 초기화 했는지 확인합니다.
    • 그래서 자식클래스의 지정init에서 부모클래스의 init 을 호출하기 전에 자신의 모든 (기본값이 없는) 저장 프로퍼티에 값을 할당해주어야 합니다.
  2. 자식클래스의 지정이니셜라이저는 상속받은 프로퍼티에 값을 할당하기 전에 반드시 부모클래스의 이니셜라이저를 호출해야 합니다
  3. 편의이니셜라이저는 자신의 클래스에 정의한 프로퍼티를 포함하여 그 어떤 프로퍼티도 값을 할당하기 전에 다른 이니셜라이저를 호출해야합니다.
  4. 초기화 1단계를 마치기 전까지는 이니셜라이저는 인스턴스 메서드를 호출할 수 없습니다. 또, 인스턴스 프로퍼티의 값을 읽어들일수도 없습니다. self 프로퍼티를 자신의 인스턴스를 나타내는 값으로 활용할 수도 없습니다.

클래스의 인스턴스는 초기화 1단계를 마치기 전까지는 아직 유효하지 않는다. 프로퍼티는 읽기만 가능하며, 메서드는 호출될 수 있을 뿐이다. 클래스의 인스턴스가 초기화 1단계를 마쳤을 때 비로서 유효한 인스턴스가 되는 것이다.

4가지 안전확인에 근거하여 2단계 초기화 살펴보기

1단계 (Phase1)

  1. 클래스가 지정 또는 편의 이니셜라이저를 호출한다.
  2. 그 클래스의 새로운 인스턴스를 위한 메모리가 할당된다. 이때, 메모리는 아직 초기화 되지않은 상태이다.
  3. 지정이니셜라이저는 클래스에 정의된 모든 저장프로퍼티에 값이 있는지 확인한다. | 이때, 현재 클래스 부분까지의 저장프로퍼티를 위한 메모리는 이제 초기화된 상태이다.
  4. 지정이니셜라이저는 부모클래스의 이니셜라이저가 같은 동작을 행할 수 있도록 초기화를 양도한다.
  5. 부모클래스는 상속체인(inheritance chain)을 따라 최상위 클래스에 도달할때까지 이 작업을 반복한다.

최상위 클래스에 도달했을 때, 최상위 클래스까지 모든 저장 프로퍼티에 값이 있다고 확인하면 해당 인스턴스의 메모리는 모두 초기화 된 것이다. -> 1단계 완료

image

2단계 (Phase2)

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

image

Ref

https://hcn1519.github.io/articles/2019-02/swift-init-class-deep

chaneeii commented 1 year ago

https://hcn1519.github.io/articles/2019-02/swift-init-class-deep https://velog.io/@wansook0316/Two-Phase-Initialization-2%EB%8B%A8%EA%B3%84-%EC%B4%88%EA%B8%B0%ED%99%94