Open Do-hyun-Kim opened 1 year ago
Swift의 Initializer 규칙
convenience init은 같은 클래스에서 다른 이니셜라이저를 호출해야한다.
Designated init의 보조이기 때문에 위에서 선언한 init을 활용하여 선언해야 한다.
<Initializer의 종류>
default
값으로 초기화를 시켜줄 수 있다.Designated Initializer
를 호출해야 한다.클래스가 상속관계에 있을때 or 클래스가 Designated Initializer
와 Convenience Initializer
둘다 가지고 있을 때 생성자가 또다른 생성자를 호출하는 방식이다. Initializer Delegation
호출을 위한 룰은 아래와 같다.
Designated initializer
는 부모클래스의 Designated initializer
를 호출해야 한다.Convenience Initializer
는 같은 클래스에 정의된 다른 생성자를 호출해야한다.Convenience Initializer
는 결국에는 Designated Initializer
를 호출해야한다.Swift에서는 클래스를 생성하는 2단계 과정이 존재한다.
1단계: 클래스 내부에 선언된 프로퍼티가 초기화된다.
1: Designated
혹은 Convenience Initializer
가 호출된다.
2: 클래스를 위한 힙 메모리가 할당된다. 아직 메모리에 데이터가 초기화된 상태는 아니다.
3: Initializer Delegation
으로 인해 마지막에 Designated Initializer
에서 클래스의 모든 프로퍼티들이 초기화된다. 메모리에 데이터가 초기화된 상태이다.
4: 상속관계에 있을경우 부모 클래스의 생성자를 호출함으로서 Initializer Delegation
을 수행한다.
5: 위 과정을 최상위 부모 클래스의 Designated Initializer
가 호출될 때까지 진행한다.
6: 최상위 부모 클래스의 Designated Initializer
가 호출됨으로서 상속관계에 있는 모든 클래스의 프로퍼티들이 초기화되었고, 메모리에 모든 데이터 역시 초기화 된 상태가 된다.
2단계: 클래스 내부의 모든 프로퍼티가 초기화 된 후, 이 프로퍼티들을 접근/수정 할 수 있다.
1: 최상위 부모 클래스의 Designated Initializer
가 호출 된 후에야 Designated Initializer
내에서 클래스의 프로퍼티와 메서드, self
에 접근할 수 있게 되고, 차례로 바로 아래의 자식 클래스 Designated Initializer
내에서 클래스의 프로퍼티와 메서드에 접근할 수 있게 된다.
2: 마지막으로 모든 Convenience Initializer
내에서 클래스의 프로퍼티와 메서드, self
에 접근할 수 있게 된다.
Swift는 Two-Phase Initialization 을 에러없이 안전하게 수행하기 위한 안전 방침을 따른다.
Safety Check 1: 상속관계에서 자식 클래스의 Designated Initializer
는 부모 클래스의 생성자를 호출(Initializer Delegation
)하기 전에 해당 자식 클래스의 모든 프로퍼티들이 초기화가 되어 있어야 한다.
Safety Check 2:자식 클래스의 Designated Initializer
는 부모 클래스의 생성자를 호출하기 전에 부모 클래스로 부터 상속받은 프로퍼티를 초기화 해서는 안된다. 상속받은 프로퍼티를 자식 클래스의 Designated Initializer
에서 사전에 초기화를 진행해버리면 이후에 부모 클래스의 생성자에서 한번더 초기화를 시도하기 때문에 의도치 않은 값이 담기게 된다.
Safety Check 3: Convenience Initializer
는 클래스의 다른 생성자를 호출하기 전에 프로퍼티를 초기화해서는 안된다. 그렇지 않으면 이후에 호출되는 Designated Initializer
에 의해 의도치 않은 값이 담기게 된다.
Safety Check 4: 모든 생성자는 상속관계에 있는 모든 클래스들의 모든 프로퍼티가 초기화 되기 전까지는 모든 프로퍼티, 메서드 그리고 self
에 접근/사용할 수 없다.
🗣️ Convenience init에 대해 설명하시오.
self.init()
✏️ Initialization Rule
Super Class
의 Designated Initialization을 호출해야 한다.✔️ Initialization Safety check
super.init
을 호출하기 전에 현재 클래스에서 정의한stored properties
의 값이 delegate up 되기 이전에 모두 초기값을 가지고 있어야 한다.stored properties
의 크기를 통해서 크기를 결정 하게 되며,subClass
의 메모리 크기는superClass
로 가기 전에 결정지게 된다.designated initializer
는 상속받은 property의 값을 넣기 전에superClass
의 initializer를 호출해야 한다.(delegate up)convenience initializer
에서 property에 값을 설정하기 전에initializer delegation
을 수행해야한다.🧐 two-phase initialization
designated initializer
혹은convenience initializer
호출해야한다.stored properties
에 들어가는 데이터 크기를 모르기 때문에 정확한 메모리 크기가 설정되어 있지 않다.designated initializer
가 모든stored properties
가 설정되었는지 체크 후, property들에 대한 메모리 init을 수행한다.subClass
의 작업을 마치고superClass
에서 위의 과정과 동일한 작업을 수행한다.superClass
가 모든 properties가 값이 있는지 확인 후, init 작업이 완료된다.superClass
는 property 값을 변경할 기회를 얻게 된다.superClass
부터 마지막subClass
의 순서로 주어진다.convenience initializer
라면,designated initializer
부터 우선적으로 self의 값을 변경할 기회를 얻게 된다. 이 작업을 마치면 최종적으로convenience initializer
가 값을 변경할 기회를 얻게 된다.📝 참고 사이트