-
swift - Initializer and Deinitializer #4 (Initializer Delegate)swift 2021. 1. 12. 16:07
Initializer Delegate
값 형식과 참조 형식에서 서로 다른 규칙으로 구현된다.
값 형식은 상속이 불가능하고 init 종류가 하나기 때문에 상대적으로 단순
값 형식의 Initializer
init이 실행이 완료되었을때 모든 속성이 초기화 되기만 하면 어떤 패턴으로 구현되어도 상관 없다.
참조 형식의 Initializer
상속을 지원하고 구현할 수 있는 init의 종류가 두가지이기 때문에 복잡
특히 상속 계층을 따라 올라가면서 모든 init이 순서대로 호출되는 것이 매우 중요
규칙
1. designated init은 반드시 super class의 designated init을 호출해야한다. -> Delegate up
* 파란색이 Deisgnated init 회색은 convenience init
2. convenience init은 반드시 동일한 클래스의 init을 호출해야 한다.
3. convenience init을 호출햇을때 최종적으로 동일한 클래스의 designated init이 호출되어야 한다.
struct Size { var width: Double var height: Double init(w: Double, h: Double) { width = w height = h } init(value: Double) { // init에서 다른 init을 호출하는 것을 delegate라고 한다. self.init(w: value, h: value) } } class Figure { let name: String init(name: String) { self.name = name } convenience init() { // 규칙 2. convenience init은 동일한 class의 init을 호출한다. // 규칙 3. convenience init을 호출할때는 최종적으로 designated init이 호출되어야 한다. self.init(name: "Unknown") } } class Rectangle: Figure { var width = 0.0 var height = 0.0 init(n: String, w: Double, h: Double) { // first phase width = w height = h // 규칙 1. delegate up (subClass의 init에서는 superClass의 init을 호출해야 함) super.init(name: n) // second phase } convenience init(value: Double) { self.init(n: "rect", w: value, h: value) } } class Square: Rectangle { convenience init(value: Double) { // convenience init에서는 어떠한 경우에도 delegate up이 불가능 -> super.init호출이 불가능 self.init(n: "Square", w: value, h: value) } convenience init() { self.init(value: 0.0) } }
Class Initializer는 두단계로 수행된다.
1. First phase
선언되어 있는 모든 속성이 초기화
초기화는 subclass -> superclass 상속계층을 따라 아래서 위로
모든 속성이 초기화되면 첫번째 단계가 완료되고 인스턴스의 유효성이 확보됨
2. Second phase
바로 이어서 두번째 단계가 시작되는데
super class -> Subclass
첫번째에서 할 수 없었던 작업을 수행한다.
인스턴스 속성에 접근하거나 메소드를 호출하는 것도 가능
부가적인 단계기 때문에 자동적으로 수행되는 예도 많음
Square 클래스의 파라미터가 없는 init 실행하면 밑에와 같은 순서로 initialization이 진행된다.
first phase 완료
second phase 완료
'swift' 카테고리의 다른 글