초기화 (Initialization)
클래스, 구조체, 열거형 인스턴스를 사용하기 위해 준비 작업을 하는 단계
init
키워드로 초기화 구문 생성deinit
키워드 사용)인스턴스의 저장 프로퍼티는 사용 전 반드시 초기화되어야 함
init
내부에서 저장 프로퍼티의 값 설정 시struct Farenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
var f = Farenheit() // init() 실행
// var f = Farenheit.init()
print("Default temperature is \(f.temperature)"
// Default temperature is 32.0
프로퍼티의 선언과 동시에 값을 할당하여 초기화할 수 있다.
초기화 구문에 파라미터를 정의해 사용할 수 있다.
init(parameterA:parameterB:)
or init(_:)
, ...nil
로 초기화되어, 해당 프로퍼티는 초기화 구문 내에서 초기값을 넣어주지 않아도 된다.let
)에 값을 할당하는 것을 허용한다.class SomeClass {
let someIntConstant: Int
var someIntVariable: Int
var someString: String? // 자동으로 초기값 nil 대입
init(constant someIntConstant: Int, _ someIntVariable: Int) {
self.someIntConstant = someIntConstant // let 할당 허용
self.someIntVariable = someIntVariable
}
}
let someClass = SomeClass(constant: 10, 30)
someClass.someIntConstant // 10
someClass.someIntVariable // 30
someClass.someString // nil
모든 프로퍼티의 초기값이 설정되어 있고, init
구문이 하나도 없다면
모든 프로퍼티의 초기값을 기준으로 인스턴스를 생성하는 기본 초기화 구문을 제공
class SomeClass {
var stringA: String?
var stringB = "string B"
var intC = 1
}
let someClass = SomeClass()
someClass.stringA // nil
someClass.stringB // string B
someClass.intC // 1
구조체는 init
구문을 하나도 사용하지 않았다면, 모든 프로퍼티를 인자로 하는 생성자를 자동으로 생성
struct SomeStruct {
var someBool = false
var someInt: Int
}
let someStruct = SomeStruct(someBool: true, someInt: 1)
// or
let someStruct = SomeStruct(someInt: 2) // someBool은 초기값이 존재하므로 따로 초기화하지 않아도 된다.
초기화 구문에서 다른 초기화 구문을 호출 가능, 이를 이니셜라이저 위임 (Initializer Delegation)이라 한다.
값 타입 (struct
, enum
)
self.init
을 사용하여 다른 이니셜라이저를 호출할 수 있다.self.init
은 이니셜라이저 내부에서만 사용할 수 있다.extension
에서 구현해야 한다.참조 타입 (class
)
super.init(...)
)클래스의 모든 저장 프로퍼티와 상속받은 모든 프로퍼티는 초기화 단계에서 반드시 초기값이 할당되어야 한다.
편의 이니셜라이저(Convenience Initializer)는 초기화 단계에서 미리 지정된 값을 사용해서 최소한의 입력으로 초기화를 할 수 있도록 해주는 이니셜라이저
init
앞에 convenience
키워드를 붙여 선언할 수 있다.지정 이니셜라이저(Designated Initializer)와 편의 이니셜라이저 사이의 관계를 단순하기 위해 이니셜라이저 위임은 다음 세 가지 규칙을 따름
다음 그림으로 이해할 수 있다.
Swift에서 클래스 초기화는 2단계로 진행된다.
Objective-C의 Two-Phase Initialization
Swift의 2단계 초기화는 Objective-C와 유사하다.
차이점은 1단계에서인데, Objective-C는 모든 프로퍼티에 zero 혹은 null을 할당한다.
Swift에서는 커스텀 초기값을 할당할 수 있고, 0과 nil이 잘못된 초기값으로 지정된 경우 대처할 수 있다.
컴파일러는 Two-Phase Initialization이 에러 없이 끝나는 것을 보장하기 위해 4단계의 안전 확인(safety-check)을 한다.
지정 이니셜라이저는 클래스 안에서 초기화를 Superclass의 이니셜라이저에게 위임하기 전에 모든 프로퍼티를 초기화해야 한다.
지정 이니셜라이저는 상속된 값을 할당하기 전에 Superclass의 이니셜라이저로 위임을 넘겨야 한다.
편의 이니셜라이저는 반드시 프로퍼티를 할당하기 전에 다른 이니셜라이저로 위임을 넘겨야 한다.
이니셜라이저는 초기화의 1단계가 끝나기 전에는 self
의 값을 참조하거나 인스턴스 프로퍼티, 메서드 등을 호출하거나 읽을 수 없다.
Subclass에서 Superclass의 이니셜라이저를 상속하지 않는다.
init
키워드 앞에 override
키워드를 붙인다.let
)는 변경할 수 없다.특정 상황에서 Subclass는 Superclass의 이니셜라이저를 자동으로 상속받는다.
초기화 과정 중 초기화에 실패할 가능성이 있는 이니셜라이저를 선언할 수 있다.
init?(...)
의 형태로 사용nil
을 반환한다.return nil
이 존재하더라도, 성공하는 경우 값을 반환하지 않는다.대표적인 init? 의 사용
Int
의 이니셜라이저 중 하나로,String
을Int
로 변환하는 이니셜라이저이다.
let intFromString = Int("1")
위 코드에서intFromString
의 타입은Int?
가 된다.
let intFromString = Int("1")!
위 코드에서intFromString
의 타입은Int
이다. (강제 언래핑)
let intFromString = Int("a")
위 코드에서intFromString
은nil
이다.
Superclass의 실패 가능한 이니셜라이저를 Subclass의 실패 불가능한 이니셜라이저로 오버라이딩 가능 (반대는 불가능)
init?
을 init!
으로 오버라이딩할 수 있다.모든 Subclass에서 반드시 구현해야 하는 이니셜라이저는 required
키워드를 붙여 선언할 수 있다.
class SomeClass {
required init() { ... }
}
class SomeSubclass: SomeClass {
required init() { ... } // 무조건 구현해야 함
}
단순 값 할당이 아닌 복잡한 계산을 필요로 한다면, 클로저나 함수를 이용해 초기화 가능
self
나 다른 프로퍼티를 사용할 수 없다.class SomeClass {
let someProperty: SomeType = {
...
return someValue
}()
}