일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Human interface guide
- UICollectionView
- rxswift
- UITextView
- 리펙터링
- Protocol
- 스위프트
- uitableview
- swift documentation
- Refactoring
- 클린 코드
- combine
- collectionview
- map
- Clean Code
- uiscrollview
- Observable
- Xcode
- swiftUI
- RxCocoa
- clean architecture
- MVVM
- 리팩토링
- ios
- tableView
- 리펙토링
- HIG
- 애니메이션
- SWIFT
- ribs
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[swift] 18. 초기화(initialize) 심화 개념 본문
Default Initialize (기본 이니셜라이저)
클래스에서 이니셜라이저를 정의하지 않은 경우
Designated Initializers and Convenience Initializers
Designated Init(지정초기화): 클래스의 모든 프로퍼티를 초기화
Convenience Init: 미리 지정된 값을 사용해서 최소한의 입력으로 초기화 할 수 이도록 해주는 초기자
- Designated는 반드시 위임을 superclass로 해야하고, convenience는 같은 레벨에서 해야함
- 클래스 타입은 반드시 한 개 이상의 Designated Initialize가 있어야 함
- Designated Initilize는 반드시 직계 superclass의 지정 init을 호출해야함
- Convenience Initilize에서는 반드시 Designated init이 호출되어야 함
2단계 초기화 (Two-Phase Initialization)
- 원래 스위프트에서 클래스는 2단계를 통해서 초기화 됨
첫 번째 단계: 각 저장된 프로퍼티를 정해진 초기값으로 초기화
두 번째 단계: 새로운 인스턴스의 사용이 준비됐다고 아렬주기 전에 저장된 프로퍼티에 대해 커스터마이징
2단계 초기화를 위한 safety-check
1단계) Designated Init은 superclass의 초기자에게 위임하기 전에 모든 프로퍼티를 초기화 해야함
(메모리에서 객체는 모든 저장된 프로퍼티가 초기 상태를 갖어야만 완전히 초기화 된 것으로 간주하기 때문)
* 핵심: super.init호출 할 경우, 현재 클래스의 초기화를 중단한 후 메모리에 올려짐 (메모리에 올려질 때 초기화가 되어있어야 오류x)
// Designated Init을, 프로퍼티 초기화 한 후 부른 적합한 경우
class A {
init () {}
}
class B: A {
let a: Int
init(i: Int) {
a = i
super.init() // success
}
}
2단계) 서브클래스에서 상속된 값을 사용하기 전에 반드시 superclass의 초기자로 위임을 넘겨야 함
(super.init을 호출하지 않으면 아직 super클래스가 초기화 되지 않은 상태이므로, 상속된 값을 사용할 수 없음)
// superclass를 먼저 초기화 하지 않고 상속된 값을 사용하려고 한 경우
class A {
let b = 2
init () {}
}
class B: A {
let a: Int
init(i: Int) {
a = 1
print(b) // error: b의 값이 아직 초기화 되지 않음
super.init()
}
}
// superclass의 초기자에게 위임하기 전에 모든 프로퍼티를 초기화 하지 않은 경우
class A {
let b = 2
init () {}
}
class B: A {
let a: Int
init(i: Int) {
super.init() // error
a = 1
print(b)
}
}
// 적절하게 초기화한 경우: super.init하기 전에 본 클래스의 프토퍼티 모두 초기화, 상속된 값을 사용하기 전에 superclass 초기화
class A {
let b = 2
init () {}
}
class B: A {
let a: Int
init(i: Int) {
a = 1
super.init()
print(b)
}
}
3단계) convenience Init은 반드시 어떤 프로퍼티를 할당하기 전에 다른 초기자로 위임을 넘겨야 함
(convenience init 후 다른 초기자로 위임을 넘기면, convenience init한 값이 묻힘)
class A {
let b = 2
convenience init(abc: Int) {
b = abc // error: 여기서 초기화 해도, self.init()에서 다시 2로 덮어씌워짐
self.init()
}
}
class A {
var b = 2
convenience init(abc: Int) {
self.init()
b = abc // success
}
}
4단계) 1단계를 하지 않으면 self로 property나 메서드를 참조할 수 없음
class A {
var b = 2
convenience init(abc: Int) {
self.b = 1 // error
self.init()
}
}
상속과 오버라이딩
- subclassd에서 superclass의 이니셜라이저를 상속받지 않음
(무분별하게 상속되어, subclass에서 잘못 초기화 되는 것을 막기 위함)
직접 override키워드를 붙여야 함
class A {
var a: Int
init() {
a = 1
}
init(a: Int) {
self.a = a
}
convenience init(abc: Int) {
self.init()
a = abc
}
}
class B: A {
let b: Int
init(a: Int, b: Int) {
self.b = b
super.init(a: a)
}
override convenience init(abc: Int) {
self.init(a: a, b: 123)
}
}
Failable Initializers
- 초기화시, 실패할 수 있는 초기화 (성공시 Optional값 반환, 실패시 nil반환)
- 이 초기화 역시 override이 가능
class A {
var a: Int
init?(b: Int) {
if b == 0 { return nil }
self.a = b
}
}
print(A(b: 0)) // nil
클로저를 이용하여 메서드 or 프로퍼티 값 초기화
- 클로저 끝에 괄호"()" 사용
- 클로저를 초기자에서 사용하면 self를 통해 달느 프로퍼티를 사용 불가
(클로저 실행 시점에서의 다른 프로퍼티들은 초기화가 끝난 시점이 아니기 때문)
class A {
var a: Int = {
return 123
}()
}
Required init
- 서브클래스에서 꼭 선언해야 하며, 구현은 하지 않아도 됨
'swift 5 문법' 카테고리의 다른 글
[iOS - swift] (초기화) designated init vs convenience init (0) | 2021.06.16 |
---|---|
[swift] 19. struct vs. class (0) | 2020.10.01 |
[swift] 17. 연산자 재정의 (0) | 2020.09.27 |
[swift] 16. 고차 함수(Higher-order function) (0) | 2020.05.24 |
[swift] 15. 객체지향 vs 함수형 (0) | 2020.04.20 |