Initialization in Swift - 2

권승용(Eric)·2024년 10월 30일

TIL

목록 보기
3/38

클래스 상속과 초기화

  • 초기화 과정에서 클래스가 상속받는 슈퍼클래스의 저장 프로퍼티들도 초기값을 설정해 주어야 한다.
  • Swift는 클래스 타입이 모든 저장 프로퍼티가 초기값을 가지게 하기 위해 두 가지 초기자를 지원한다.
    • 지정 초기자 (Designated Initializers)
    • 편의 초기자 (Convenience Initializers)

지정 초기자와 편의 초기자

  • 지정 초기자는 클래스의 기본 초기자이다.
  • 지정 초기자는 해당 클래스의 모든 저장 프로퍼티를 초기화하고, 적절한 슈퍼클래스 초기자를 호출해 슈퍼클래스의 초기화 과정을 이어간다.
  • 보통 클래스당 하나의 지정 초기자를 가지며, 초기화 프로세스가 슈퍼 클래스 체인 위로 이어지도록 하는 지점이다.
  • 모든 클래스는 하나 이상의 지정 초기자를 갖고 있어야 한다.
    • 어떤 경우엔 슈퍼클래스로부터 지정 생성자를 상속해 이런 요구사항을 충족할 수 있다.
// 지정 생성자 문법
init(<#parameters#>) {
   <#statements#>
}
  • 편의 초기자는 클래스에 대한 초기자를 지원하는 보조 초기자이다.
  • 지정 생성자보다 더 적은 파라미터를 가지는 편의 생성자를 생성할 수 있다.
  • 좀 더 편리하게 사용하고 싶거나, 특정한 유즈 케이스 또는 입력값 타입에 대한 클래스 인스턴스를 생성하고 싶을 때 편의 초기자를 사용하면 된다.
  • 편의 초기자가 필요하지 않다면 굳이 작성할 필요는 없다.
// 편의 생성자 문법
convenience init(<#parameters#>) {
   <#statements#>
}

클래스 타입의 초기자 위임

  • 지정 생성자와 편의 생성자의 관게를 단순화하기 위해서, 초기자 간의 delegation 호출에 대해 Swift는 아래 세 가지 규칙을 적용한다.
    • 지정 생성자는 바로 위 슈퍼클래스의 지정 생성자를 호출해야만 한다.
    • 편의 생성자는 같은 클래스의 다른 초기자를 호출해야만 한다.
    • 편의 생성자는 궁극적으로 지정 생성자를 호출해야만 한다.
  • 이 규칙을 외우는 쉬운 방법은 아래와 같다:
    • 지정 생성자는 항상 위쪽 방향으로 위임됨
    • 편의 생성자는 항상 수평 방향으로 위임됨

  • 이 규칙은 사용자가 클래스 인스턴스를 생성하는 데에는 영향을 미치지 않는다. 오직 클래스 초기자의 구현을 작성하는 방법에만 영향을 미친다.

2단계 초기화 (2-phase initialization)

  • Swift의 클래스 초기화는 2단계 과정을 거친다.
  • 첫 번째 단계에서는 각 저장 프로퍼티는 해당 프로퍼티를 가지는 클래스에 의해 초기화된다.
  • 모든 저장 프로퍼티에 대한 초기 상태가 결정되면 두 번째 단계가 시작되고, 각 클래스는 새로운 인스턴스가 사용될 수 있는 상태가 되기 전에 저장 프로퍼티를 변경할 기회를 얻게 된다.
  • 이러한 2단계 초기화는 초기화를 안전하고 유연하게 만든다.
    • 초기화 이전에 프로퍼티 값에 접근하는 것을 막는다.
    • 다른 초기자로 인해 예상치 못하게 다른 값으로 설정되는 것을 예방한다.

Swift의 2단계 초기화는 Objective-C의 초기화 과정과 비슷하다. 가장 큰 차이점은 1단계 과정에서 Objective-C는 0 또는 null 값을 모든 프로퍼티에 할당한다. Swift의 초기화 과정은 커스텀 초기값을 지정할 수 있고 0이나 nil이 유효한 초기값이 아닌 타입에 대응할 수 있다는 점에서 더욱 유연하다.

  • Swift의 컴파일러는 4단계의 안정성 체크를 통해 2단계 초기화가 에러 없이 완료됨을 보장한다:

  • 안정성 체크 1

    • 지정 초기자는 슈퍼클래스 초기자에게 초기화 과정을 위임하기 전에 해당 클래스의 모든 저장 프로퍼티를 초기화해야 한다.
  • 안정성 체크 2

    • 지정 초기자는 상속된 프로퍼티에 값을 할당하기 이전에 슈퍼클래스 초기자에게 초기화 과정을 위임해야 한다. 그렇지 않으면 지정 초기자에서의 값 할당은 슈퍼클래스 초기화 과정에서 덮어씌워질 것이다.
  • 안정성 체크 3

    • 편의 생성자는 프로퍼티에 값을 지정하기 전에 다른 초기자에게 초기화 과정을 위임해야 한다. 그렇지 않으면, 편의 생성자가 설정하는 새로운 값은 편의 생성자에서 호출하는 지정 생성자에 의해 덮어씌워질 것이다.
  • 안정성 체크 4

    • 1단계 초기화가 완료되기 이전에 초기자는 인스턴스 메소드를 호출하거나, 인스턴스 프로퍼티로부터 값을 읽거나, self를 값으로서 참조할 수 없다.
  • 1단계 과정이 끝나기 전에는 클래스 인스턴스가 완전히 유효하지는 않다.

    • 1단계 과정이 끝나고 클래스 인스턴스가 유효화된 후에야 프로퍼티에 접근이 가능해지고 메소드 호출이 가능해진다.
  • 1단계 과정

    • 지정 또는 편의 초기자가 클래스에서 호출된다.
    • 새로운 인스턴스를 위한 메모리가 할당된다. (아직 초기화되지는 않음)
    • 클래스의 지정 초기자가 모든 저장 프로퍼티에 값을 지정한다. 이 시점에서 해당 저장 프로퍼티들에 대한 메모리가 초기화 완료된다.
    • 지정 초기자는 상속받은 슈퍼클래스의 초기자를 호출해 슈퍼클래스의 저장 프로퍼티 초기화를 진행한다.
    • 이는 슈퍼클래스 체인의 끝에 도달할 때 까지 연속적으로 진행된다.
    • 체인의 마지막 클래스의 저장 프로퍼티들이 값을 할당받게 되면, 인스턴스의 메모리는 완전히 초기화 완료된 것으로 간주되고 1단계 과정이 끝난다.
  • 2단계 과정

    • 체인의 가장 위에서 다시 내려오며, 체인의 각 지정 초기자들은 인스턴스를 변경할 수 있다. 초기자들은 self에 접근해 프로퍼티를 변경할 수 있고, 인스턴스 메소드를 호출할 수 있다.
    • 마지막으로, 체인의 편의 생성자들도 인스턴스를 변경하고 self로 작업할 수 있게 된다.
profile
ios 개발자에용

0개의 댓글