인스턴스가 생성될 때 모든 저장 프로퍼티에는 정상적인 값들이 초기화되어있어야 한다는 규칙이 존재한다.
위의 코드처럼 jason이라는 PersonA의 인스턴스를 생성할 때, 저장 프로퍼티 중 하나라도 초기화되어있지 않다면 오류가 발생한다.
하지만 프로퍼티 기본값을 지정하기 어려운 경우가 있을 수 있다. 그럴 때 이니셜라이저를 통해 인스턴스가 가져야 할 초기값을 전달할 수 있다.
만약, 닉네임이 없는 사람의 경우 nickName 변수의 초기값이 존재하지 않는다. 그럴 경우 옵셔널을 사용한다. 프로퍼티의 초기값이 꼭 필요하지 않을 때 사용!
그런데 아직도 좀 불편함 ㅎ.ㅎ;;
self.name = name
self.age = age
이 코드가 두개의 이니셜라이저에서 중복으로 나타난다. 중복을 줄일 방법이 없을까?
init 안에서 init을 불러 해결 가능! 단, 이렇게 사용하려면 호출자인 init에게 convenience 키워드를 붙여줘야 한다.
일반 옵셔널은 알겠는데, 암시적 추출 옵셔널은 이니셜라이저와 관련하여 쓰일 수 있는 부분이 없을까?
암시적 추출 옵셔널은 다음의 조건을 갖는 프로퍼티에 사용된다.
이니셜라이저 매개변수로 전달되는 초기값이 잘못된 경우 인스턴스 생성에 실패할 수 있다. (주로 매개변수로 넘어온 값이 정상범주를 넘어간다거나 원하는 범위의 값이 아닌 경우가 이에 해당) 인스턴스 생성에 실패하면 nil을 반환한다. 따라서 실패가능한 이니셜라이저의 반환타입은 옵셔널 타입이다.
위의 경우, monika는 나이가 0~120에 속하지 않아 인스턴스 생성에 실패하고, no는 이름이 없으므로 인스턴스 생성에 실패해 nil이 반환된다.
leejung은 두 if문 조건을 통과하고 self 세팅을 거쳐 정상적으로 생성된다.
deinit은 클래스(클래스 타입에만 사용 가능!)의 인스턴스가 메모리에서 해제되는 시점에 자동으로 호출된다. 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있다. deinit은 또한 매개변수를 가질 수 없다.
class PersonC {
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
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
class Puppy {
var name: String
var owner: PersonC!
init(name: String) {
self.name = name
}
func goOut() {
print("\(name)가 주인 \(owner.name)와 산책을 합니다")
}
}
class PersonE {
var name: String
var pet: Puppy?
var child: PersonC
init(name: String, child: PersonC) {
self.name = name
self.child = child
}
deinit {
if let petName = pet?.name {
print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")
self.pet?.owner = child
}
}
}
let jenny: PersonC = PersonC(name: "jenny", age: 10)
let happy: Puppy = Puppy(name: "happy")
happy.owner = jenny
var donald: PersonE? = PersonE(name: "donald", child: jenny)
donald?.pet = happy
donald = nil // donald 인스턴스가 더이상 필요 없으므로 메모리에서 해제
// donald가 jenny에게 happy를 인도합니다
야곰의 스위프트 기본 문법 강좌를 수강하며 작성한 내용입니다.