프로그래밍iOS/Swift 개발자

스위프트에서 초기화 위임(Initializer Delegation)이란 무엇인지, designated와 convenience 초기화자 간의 위임 규칙이 어떻게 작용하는지, 그리고 이것이 상속에 미치는 영향은 무엇인지 설명해 주세요.

Hintsage AI 어시스턴트로 면접 통과

답변.

초기화 위임(Initializer Delegation)은 스위프트에서 클래스의 초기화 과정을 위한 체계로 내장되어 있습니다. 스위프트는 기본 초기화자(designated initializer, 클래스의 모든 속성을 완전히 초기화할 책임이 있는 주요 초기화자)와 편리 초기화자(convenience initializer, 다양한 매개변수 세트를 사용하여 인스턴스를 생성하는 데 도움을 주는 보조 초기화자) 간에 역사적으로 구분이 있습니다.

문제: 클래스와 그 상속자 사이에서 초기화자가 무질서하게 실행될 경우, 기본 클래스가 완전히 초기화되지 않거나 초기화가 한 번 이상 진행되는 상황이 발생할 수 있으며, 이로 인해 잘못된 객체가 생성될 수 있습니다.

해결책 — 엄격한 규칙:

  1. Designated 초기화자는 항상 슈퍼클래스의 designated 초기화자를 호출해야 합니다.
  2. Convenience 초기화자는 항상 동일 클래스 내의 다른 초기화자(디자인 또는 다른 convenience)를 호출해야 합니다.
  3. Convenience는 직접적으로 슈퍼클래스를 초기화할 수 없습니다.

코드 예시:

class Vehicle { var wheels: Int // Designated initializer init(wheels: Int) { self.wheels = wheels } // Convenience initializer convenience init() { self.init(wheels: 4) } } class Car: Vehicle { var color: String // Designated initializer init(wheels: Int, color: String) { self.color = color super.init(wheels: wheels) } // Convenience initializer convenience init(color: String) { self.init(wheels: 4, color: color) } }

주요 특징:

  • 서로 다른 매개변수 세트를 가진 인스턴스를 생성할 때 최소한의 코드 중복이 필요합니다.
  • 안전한 클래스 상속을 지원합니다.
  • 객체의 모든 속성을 올바르게 초기화하도록 보장합니다.

곤란한 질문들.

질문 1: convenience initializer가 직접 super.init을 호출할 수 있습니까?

아니요, convenience initializer는 항상 현재 클래스의 다른 초기화자에게 초기화를 위임하며, 그 이후에 슈퍼클래스의 designated initializer를 호출할 수 있습니다.

질문 2: 서브클래스에서 required 초기화자를 구현하지 않으면 어떻게 됩니까?

슈퍼클래스에 required 초기화자가 있는 경우, 반드시 모든 서브클래스에서 이를 오버라이드해야 하며(필요한 경우 required 사용), 그렇지 않으면 컴파일러 오류가 발생합니다.

질문 3: convenience init과 convenience required init의 차이점은 무엇입니까?

convenience required init은 특정 convenience 초기화자가 슈퍼클래스에서 required로 선언된 경우, 상속 계층에서 초기화 지원을 보장하기 위해 필요합니다.

일반적인 오류 및 안티 패턴

  • 잘못된 convenience/init 호출 순서와 속성 초기화 불일치.
  • 서브클래스에서 required 초기화자를 구현하지 않음.
  • convenience에서 super.init을 호출함으로써 잘못된 상태가 발생.

실제 사례

부정적인 케이스

개발자가 convenience 초기화자에서 super.init을 호출했습니다. 코드는 특정 제약이 없었기 때문에 컴파일되었으나, 실행 시 객체의 모든 속성이 초기화되지 않아 오류가 발생했습니다.

장점:

  • 코드가 다른 언어의 유사한 구현을 연상시켰기 때문에 초보자에게 이해하기 쉬웠습니다.

단점:

  • 상속 시 버그가 발생하여 자식 클래스가 올바르게 초기화되지 않아 응용 프로그램이 충돌했습니다.
  • 리팩토링이 필요했습니다.

긍정적인 케이스

디자인된 초기화자와 convenience 초기화자를 명확히 구조화하여 서로를 명시적으로 호출했습니다. 로직이 스위프트 규칙에 따라 엄격하게 작동했기 때문에 초기화가 항상 투명하고 올바르게 이루어졌습니다.

장점:

  • 클래스 계층을 쉽게 확장하고 유지 관리할 수 있었습니다.
  • 중복 코드가 제거되었습니다.
  • 테스트가 쉬워졌습니다.

단점:

  • 큰 계층에서 초기화자 상속 문서화를 신중하게 해야 했습니다.