본문 바로가기

Swift

Initializer

기본이 되면서 중요한 Initializer에 관련하여 정리하였습니다.

 

Initialize -> 새로운 인스턴스를 사용할 준비를 하기 위하여 저장 프로퍼티의 초기값을 설정

 

구조체와 클래스의 인스턴스는 처음 생성할 때 옵셔널 저장 프로퍼티를 제외한 모든 저장 프로퍼티에 적절한 초기값을 할당해야 합니다.

Initializer가 실행될 때 저장 프로퍼티에 초기값을 할당할 수 있으며, 초기화 후에 값이 확정되지 않은 저장 프로퍼티는 존재할 수 없습니다.

 

기본 이니셜라이저

모든 프로퍼티에 기본값으로 초기화하여 인스턴스를 생성

-> 저장 프로퍼티의 기본값이 모두 지정되어 있고, 동시에 사용자 정의 이니셜라이저가 정의되어 있지 않은 상태에서 제공됩니다.

 

값 타입(구조체 / 열거형)의 이니셜라이저

멤버와이즈 이니셜라이저

프로퍼티의 이름으로 매개변수를 갖는 이니셜라이저로 구조체에서 제공

 

초기화 위임

값 타입에서 이니셜라이저가 다른 이니셜라이저를 호출하여면 self.init을 사용합니다.

 

클래스의 이니셜라이저

지정 이니셜라이저(Designated Intializer)

: 필요에 따라 부모클래스의 이니셜라이저를 호출할 수 있으며, 정의된 클래스의 모든 프로퍼티를 초기화

 

모든 클래스는 하나이상의 지정 이니셜라이저를 갖습니다.

부모클래스에서 지정 이니셜라이저가 자손클래스의 지정 이니셜라이저 역활을 수행한다면,

자식 클래스는 지정 이니셜라이저를 갖지 않을 수도 있습니다.

 

편의 이니셜라이저(Convenience Initializer)

: 지정 이니셜라이저를 자신 내부에서 호출

 

초기화를 좀 더 손쉽게 도와주는 역활로, 지정 이니셜라이저를 내부에서 호출합니다.

클래스의 초기화 위임

1. 자식클래스의 지정 이니셜라이저는 부모클래스의 지정 이니셜라이저를 반드시 호출

2. 편의 이니셜라이저는 자신을 정의한 클래스의 다른 이니셜라이저를 반드시 호출

3. 편의 이니셜라이저는 궁극정으로는 지정 이니셜라이저를 반드시 호출

 

Swift의 2단계 초기화

1단계:

-> 클래스에 정의한 각각의 저장 프로퍼티에 초깃값이 할당

-> 모든 저장 프로퍼티의 초기 상태가 결정되면 2단께로 돌입 및 저장 프로퍼티들을 사용자 정의할 기회를 획득

2단계:

-> 프로퍼티를 초기화하기 전에 프로퍼티 값에 접근하는 것을 막아 초기화를 안전하게 처리

-> 다른 이니셜라이저가 프로퍼티의 값을 실수로 변경하는 것을 방지

 

2단계에서 Swift 컴파일러의 Safety-Check

1. 자식클래스의 지정 이니셜라이저가 부모클래스의 이니셜라이저를 호출하기 전에 자신의 프로퍼티를 모두 초기화 했는지 확인

2. 자식클래스의 지정 이니셜라이저는 상속받은 프로퍼티에 값을 할당하기 전에 받드시 부모클래스의 이니셜라이저를 호출

3. 평의 이니셜라이저는 자긴의 클래스에 정의한 프로퍼티를 포함하여 그 어떤 프로퍼티라도 값을 할당하기 전에 다른 이니셜라이저를 호출

4. 초기화 1단계를 마치기 전까지는 이니셜라이저는 인스턴스 메서드를 호출할 수 없습니다. 또, 인스턴스 프로퍼티의 값을 읽어들일 수도 없습니다. self 프로퍼티를 자신의 인스턴스를 나타내는 값으로 활용할 수도 없습니다.

 

1단계

1. 클래스가 지정 또는 편의 이니셜라이저를 호출합니다.

2. 그 클래스의 새로운 인스턴스를 위한 메모리가 할당됩니다. 메모리는 아직 초기화되지 않은 상태입니다.

3. 지정 이니셜라이저는 클래스에 정의된 모든 저장 프로퍼티에 값이 있는지 확인합니다. 현재 클래스 부분까지의 저장 프로퍼티를 위한 메모리는 이제 초기화되었습니다.

4. 지정 이니셜라이저는 부모클래스의 이니셜라이저가 같은 동작을 행항 수 있도록 초기화를 양도합니다.

5. 부모클래스는 상속 체인을 따라 최상위 클래스에 도달할 때까지 이 작업을 반복합니다.

 

2단계

1. 최상위 클래스로부터 최하위 클래스까지 상속 체인을 따라 내려오면서 

지정 이니셜라이저들이 인스턴스를 제 각각 사용자 정의하게 됩니다.

이 단계에서는 self를 통해 프로퍼티 값을 수정할 수 있고, 인스턴스 메서드를 호출하는 등의 작업을 진행할 수 있습니다.

2. 마지막으로 각각의 편의 이니셜라이저를 통해 self를 통한 사용자 정의 작업을 진행할 수 있습니다.

 

Student 클래스의 지정 이니셜라이저(init(name:age:major))는 부모클래스의 지정 이니셜라이저를 호출하기 전에 자신의 self 프로퍼티를 이용해 major 프로퍼티의 값을 할당합니다.

-> Safety-Check 1번을 충족합니다.

 

super.init(name: name, age: age)를 통해 부모클래스의 이니셜라이저를 호출했으며 그 외에 상속받은 프로퍼티가 없으므로 부모의 이니셜라이저 호출 이후에 값을 할당해줄 프로퍼티가 없습니다.

-> Safety-Check 2번을 충족합니다.

 

편의 이니셜라이저인 convenience init(name:)은 따로 차후에 값을 할당할 프로퍼티가 없고, 다른 이니셜라이저를 호출했으므로

-> Safety-Check 3번 조건을 만족합니다.

 

마지막으로 이니셜라이저 어디에서도 인스턴스 메서드를 호출하거나 인스턴스 프로퍼티의 값을 읽어오지 않았으므로

-> Safety-Check 4번 조건도 충족합니다.

 

이니셜라이저의 상속 및 재정의

기본적으로 스위프트의 이니셜라이저는 부모클래스의 이니셜라이저를 상속받지 않습니다.

부모 클래스로부터 물려받은 이니셜라이저는 자식클래스에 최적화되어 있지 않아서, 부모 클래스의 이니셜라이저를 사용했을 때 자식클래스의 새로운 인스턴스가 완전하고 정호가하게 초기화 되지 않는 상황을 방지하고자 함입니다.

안전하고 적절하다고 판단되는 특정한 상황에서는 부모클래스의 이니셜라이저가 상속되기도 합니다. 

 

 

 

실패 가능한 이니셜라이저(Failable Initializer)

: 실패가능성을 염두하는 이니셜라이저

 

'Swift' 카테고리의 다른 글

생체인증을 통한 본인인증 제작기  (0) 2022.06.07
보안 핀코드 입력화면 제작기  (0) 2022.05.15
Memory에 대한 이해  (0) 2021.02.28
Lazy in Swift  (0) 2021.02.28