모든 클래스 저장 프로퍼티(클래스가 상속하는 모든 프로퍼티 포함)는 초기화를 통해 초깃값을 할당받아야 한다. 클래스 타입이 모든 저장 프로퍼티가 초깃값을 받을 수 있도록 초기화하는 두 가지 방법이 있다. 지정된 이니셜라이저(designated initializers
)와 편리한 이니셜라이저(convenience initializers
)다.
모든 클래스에 지정된 이니셜라이저가 적어도 하나는 존재한다.(부모 클래스에서 한 개 이상의 지정된 이닉셜라이저를 상속받을 때)
지원하지 않는다면 편리한 이니셜라이저를 사용하지 않아도 된다.
지정된 이니셜라이저 문법은 다음과 같다.
init(parameters) {
statements
}
init
키워드 전에 convenience
키워드를 붙이면 편리한 이니셜라이저가 된다.
convenience init(parameters) {
statements
}
이닉셜라이저 딜리게이션을 호출하는 규칙은 세 가지다.
클래스 이니셜라이저를 어떻게 쓰는지에만 영향을 미친다는 것을 주의하자.
클래스 초기화는 두 단계를 거친다.
부모-자식 클래스 간의 위계를 지키면서 초기화를 안전하게 할 수 있다. 스위프트는 세이프티를 네 단계 확인한다.
클래스엣거 지정 또는 편리 이니셜라이저가 호출되면 새로운 인스턴스용 메모리가 할당된다. 이때 메모리는 초기화되지 않은 상태다.
지정된 이니셜라이저를 사용할 때 저장 프로퍼티 값이 모두 할당받는 게 보장된다(이때 메모리가 초기화된다). 지정된 이니셜라이저는 이때 부모 클래스 이니셜라이저를 호출해, 최상위 클래스의 저장 프로퍼티에도 동일한 작업을 진행한다. 즉 처음 지정된 이니셜라이저를 호출한 클래스가 사용(상속이든 자신의 유니크한 프로퍼티든) 모든 프로퍼티가 초기화된다.
지정된 이니셜라이저를 통해 인스턴스를 커스터마이징할 수 있다. 즉 이니셜라이저를 통해 자기 자신을 참조할 수 있고 프로퍼티 값을 바꾸거나 인스턴스 메소드를 호출할 수 있다. 편리한 이니셜라이저 또한 커스터마이징에 사용한다. 2단계 초기화에 사용되는 이니셜라이저 순서는 (최상위 부모 클래스의 지정된 이니셜라이저 → ... → 현재 클래스의 지정된 이니셜라이저 → 현재 클래스의 편리한 이니셜라이저)다.
스위프트의 하위 클래스는 상위 클래스 이니셜라이저를 자동으로 상속받지는 않는다. 부모 클래스 이니셜라이저 상속이 안전하고 적절할 때에만 상속 가능하다. 오버라이딩을 통해 부모 클래스 이니셜라이저를 상속받자. 디폴트 이니셜라이저를 자동으로 오버라이딩할 때에도 키워드를 써야 한다는 데 주의.
자식 클래스가 부모 클래스의 편리한 이니셜라이저를 호출하려면 간접적으로 호출해야 하는데, 이때 오버라이딩 키워드를 작성하지는 않는다.
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)")
// Vehicle: 0 wheel(s)
The next example defines a subclass of Vehicle called Bicycle:
class Bicycle: Vehicle {
override init() {
super.init()
numberOfWheels = 2
}
}
let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)")
// Bicycle: 2 wheel(s)
class Hoverboard: Vehicle {
var color: String
init(color: String) {
self.color = color
// super.init() implicitly called here
}
override var description: String {
return "\(super.description) in a beautiful \(color)"
}
}
An instance of Hoverboard uses the default number of wheels supplied by the Vehicle initializer.
let hoverboard = Hoverboard(color: "silver")
print("Hoverboard: \(hoverboard.description)")
// Hoverboard: 0 wheel(s) in a beautiful silver
Vehicle
클래스는 커스텀 이니셜라이저가 없기 때문에 디폴트 이니셜라이저를 사용한다. Bicycle
클래스는 Vehicle
클래스를 상속하는 자식 클래스로 커스텀 이니셜라이저를 사용하고 있다. super
을 통해 나머지는 그대로 가져가고 있다.
Hoverboard
는 커스텀 이니셜라이저를 사용하면서도 오버라이딩하고 있다. super.init()
이 자동 사용되고 있다.
하위 클래스는 상속받은 변수 프로퍼티를 바꿀 수 있지만 상수 프로퍼티는 바꿀 수 없다는 점도 확인하자.