Swift에서는 모든 속성이 초기화 인스턴스의 종료 전에 초기화되어야 합니다. 이를 위해 초기화자는 designated(기본), convenience(보조) 및 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" } }
주요 특징:
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 초기화자를 호출하지 않아 필수 속성이 올바르게 초기화되지 않고 데이터 스키마 업데이트 후 프로덕션에서 크래시가 발생했습니다.