이니셜 라이저
- 이니셜라이저를 통해 초기값을 할당하거나, 기본값을 통해 프로퍼티를 초기화하는 경우, 프로퍼티감시자가 실행되지 않는다.
스위프트
의 모든 인스턴스
는 초기화와 동시에 모든 프로퍼티
에 유효한 값이 할당되어 있어야 한다.
프로퍼티
에 미리 기본값
을 할당해두면, 인스턴스가 생성됨과 동시에 초기값
을 지니게 된다.
프로퍼티 기본값
을 지정하기 어려운 경우에는 이니셜라이저
를 통해 인스턴스가 가져야할 초기값
을 전달할 수 있다.
- cpp, java등의
생성자
와 유사한 개념이다.
class PersonB{
var name : String
var age : Int
var nickName : String
init(name: String, age: Int, nickName: String){
self.name = name
self.age = age
self.nickName = nickName
}
}
let hana : PersonB = PersonB(name : "hana", age : 20, nickName : "하나")
let hana : PersonB = PersonB(name : "hana", age : 20, nickName : "")
class PersonC{
var name : String
var age : Int
var nickName : String?
convenience init(name: String, age: Int, nickName: String){
self.init(name: String, age: Int)
self.nickName = nickName
}
init(name: String, age: Int){
self.name = name
self.age = age
}
let jenny: PersonC = PersonC(name: "jenny", age: 10)
let mike: PersonC = PersonC(name: "mike", age: 10, nickName: "m")
class Puppy{
var name: String
var owner: PersonC!
init(name: String){
self.name= name
}
func goOut(){
print("\(name)가 주인 \(owner.name)와 산책을 나갑니다.")
}
}
let happy: Puppy = Puppy(name: "happy)
happy.goOut()
happy.owner = jenny
happy.goOut()
옵셔널 프로퍼티
- 이니셜라이저를 통해 초긱밧을 지정하고 싶지 않은 프로퍼티에는 옵셔널 타입으로 프로퍼티를 정의할 수 있다.
- 이니셜라이저를 통해 초기값이 주어지지않은 옵셔널 프로퍼티는
nil
이 할당된다.
멤버 와이즈 이니셜라이저
클래스
는 멤버와이즈 이니셜라이저를 갖지 않고, 사용자가 직접 정의한 이니셜라이저가 있지 않는 이상 기본 이니셜라이저 init()
만
존재한다.
- 따라서 만약 사용자가 이니셜라이저를 하나라도 정의했다면 기본 이니셜라이저는 사용할 수 없다. 이는
구조체
에서도 마찬가지이다.
구조체
의 경우 모든 프로퍼티가 있는 이니셜 라이저와 일부 프로퍼티만 매개변수로 갖는 이니셜라이저가 존재하기때문에 따로 이니셜라이저를 정의할 필요가 없다. 이를 멤버와이즈 이니셜라이저
라고 한다.
초기화 위임
- 값 타입인 구조체와 열거형에서는 이니셜라이저 내부에서 이니셜라이저를 호출할 수 있다.
self.init(~~)
을 통해 호출하면 된다.
- 하지만 초기화 위임을 통해 이니셜라이저를 정의했다는 것은, 이미 사용자가 이니셜라이저를 정의하고 있다는 뜻이며, 이는 기본 이니셜라이저를 사용할 수 없다는 뜻이다. 따라서 초기화 위임을 구현하고자 한다면 최소 2개 이상의
사용자 정의 이니셜라이저
가 필요하다.
실패 가능한 이니셜라이저
이니셜라이저
매개변수로 전달되는 초기값이 잘못
된 경우, 인스턴스 생성에 실패하도록 하는 역할
- 인스턴스 생성에 실패하면
nil
을 반환한다.
- 그래서 실패가능한
이니셜라이저
의 반환타입은 옵셔널
타입이다.
class PersonD{
var name: String
var age: Int
var nickName: String?
init?(name: String, age: Int, nickName: String){
if (0...123).contains(age) == false{
return nil
}
if name.characters.count == 0{
return nil
}
self.name = name
self.age = age
}
}
let john: PersonD = PersonD(name: "john", age: 10, nickName: "J")
let john: PersonD? = PersonD(name: "john", age: 23, nickName: "J")
let joker: PersonD? = PersonD(name: "joker", age: 123)
let batman: PersonD? = PersonD(name: "", age: 12)
print(joker)
print(batman)
디이니셜라이저
deinit
은 클래스의 인스턴스가 메모리에서 해제되기 직전에 호출된다.
- 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있다.
class PersonE{
var name: String
var pet: Puppy?
var child: PersonC
init(name: String, child: PersonC){
self.name = name
sel.child = child
}
deinit{
if let petName = pet?.name{
print("\(name)가 \(child.name)에게 \(petName)을 양도합니다.")
self.pet?.owner = child
}
}
}
var donald: PersonE? = PersonE(name: "donald", child: "jenny")
donald?.pet = happy
donald = nil