프로그래밍시니어 iOS 개발자

Swift에서 속성 초기화는 어떻게 이루어지나요? designated, convenience 및 required 초기화자는 어떻게 다릅니까? 초기화 계층 작업 시 어떤 주의사항이 있습니까?

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

답변.

Swift에서는 모든 속성이 초기화 인스턴스의 종료 전에 초기화되어야 합니다. 이를 위해 초기화자는 designated(기본), convenience(보조) 및 required(상속자에게 필수) 있습니다.

  • Designated 초기화자 — 주된 초기화자로, 클래스의 모든 속성을 초기화하고 슈퍼클래스의 designated 초기화자를 호출하는 역할을 합니다. 모든 클래스는 최소한 하나의 designated 초기화자를 갖고 있어야 합니다.
  • Convenience 초기화자는 보조 초기화자로, 같은 클래스의 초기화를 위임합니다(클래스 내의 다른 초기화자를 self.init(...)을 통해 호출) 하며, 다양한 매개변수 세트를 사용하여 객체 생성을 간소화합니다.
  • Required 초기화자는 모든 서브클래스가 이 초기화자를 구현해야 함을 요구합니다. required 수정자와 함께 선언됩니다.

예:

class Vehicle { let numberOfWheels: Int required init(numberOfWheels: Int) { self.numberOfWheels = numberOfWheels } } class Car: Vehicle { let brand: String // Designated initializer required init(numberOfWheels: Int) { self.brand = "Unknown" super.init(numberOfWheels: numberOfWheels) } // Convenience convenience init() { self.init(numberOfWheels: 4) self.brand = "Ford" } }

주요 특징:

  • 모든 속성은 super.init에 접근하기 전에 초기화되어야 합니다.
  • Convenience 초기화자는 항상 designated 또는 다른 convenience 초기화자 self를 호출해야 합니다.
  • Required 초기화자는 모든 상속자에서 반드시 구현되어야 합니다.

함정 질문.

designated initializer를 사용할 때 서브클래스와 슈퍼클래스의 속성을 초기화하는 순서는 어떻게 해야 하나요?

답변: 서브클래스의 모든 속성은 슈퍼클래스의 designated 초기화자(super.init)를 호출하기 전에 초기화되어야 하며, 그렇지 않으면 컴파일 오류가 발생합니다. super.init 이후에는 서브클래스의 새로운 stored 속성을 초기화할 수 없으며, 사용할 수만 있습니다.

class Parent { let parentProp: Int init(prop: Int) { parentProp = prop } } class Child: Parent { let childProp: String init(prop: Int, childProp: String) { self.childProp = childProp // 먼저 자신의 속성 super.init(prop: prop) // 그 다음 parent } }

이 주제에 대한 간과로 인한 실제 오류 예제들.


이야기

개발자가 convenience 초기화자에서 designated를 호출하지 않고 직접 require 속성에 값을 할당하려고 했습니다. 그 결과 속성이 두 번 다른 값으로 초기화되어 테스트 중 예기치 않은 동작이 발생했습니다.


이야기

깊은 클래스 계층 구조를 상속하면서 required init 선언을 잊어버렸고, 이로 인해 리플렉션을 통해 파생 타입을 올바르게 초기화할 수 없게 되어 JSON 모델 deserialization 시 크래시가 발생했습니다.


이야기

Vehicle 클래스 확장 중에 슈퍼클래스의 designated 초기화자를 호출하지 않아 필수 속성이 올바르게 초기화되지 않고 데이터 스키마 업데이트 후 프로덕션에서 크래시가 발생했습니다.