[Swift5] Initialization 2

Junyoung Park·2022년 3월 22일
0

Swift5 Docs

목록 보기
29/37
post-thumbnail
  • 다음은 Swift 5.6 Doc의 Initialization 공부 내용을 정리했음을 밝힙니다.

Initialization

클래스 상속 및 초기화

모든 클래스 저장 프로퍼티(클래스가 상속하는 모든 프로퍼티 포함)는 초기화를 통해 초깃값을 할당받아야 한다. 클래스 타입이 모든 저장 프로퍼티가 초깃값을 받을 수 있도록 초기화하는 두 가지 방법이 있다. 지정된 이니셜라이저(designated initializers)와 편리한 이니셜라이저(convenience initializers)다.

지정된 이니셜라이저와 편리한 이니셜라이저

  • 지정된 이니셜라이저: 클래스 내 모든 프로퍼티를 초기화하고 부모 클래스 초기화에 필요한 이니셜라이저를 호출한다.

모든 클래스에 지정된 이니셜라이저가 적어도 하나는 존재한다.(부모 클래스에서 한 개 이상의 지정된 이닉셜라이저를 상속받을 때)

  • 편리한 이니셜라이저: 클래스 이니셜라이저를 지원. 편리한 이니셜라이저가 지정된 이니셜라이저 파라미터의 디폴트 값을 설정하고, 지정된 이니셜라이저를 호출한다. 클래스 인스턴스를 생성할 때 호출한다.

지원하지 않는다면 편리한 이니셜라이저를 사용하지 않아도 된다.

이니셜라이저 문법

지정된 이니셜라이저 문법은 다음과 같다.

init(parameters) {
    statements
}

init 키워드 전에 convenience 키워드를 붙이면 편리한 이니셜라이저가 된다.

convenience init(parameters) {
    statements
}

클래스 타입 이니셜라이저 딜리게이션

이닉셜라이저 딜리게이션을 호출하는 규칙은 세 가지다.

  • 지정된 이니셜라이저는 부모 클래스의 지정된 이니셜라이저를 호출해야 한다.
  • 편리한 이니셜라이저는 같은 클래스의 다른 이니셜라이저를 호출해야 한다.
  • 편리한 이니셜라이저는 궁극적으로 지정된 이니셜라이저를 호출해야 한다.

클래스 이니셜라이저를 어떻게 쓰는지에만 영향을 미친다는 것을 주의하자.

두 단계의 초기화

클래스 초기화는 두 단계를 거친다.

  1. 저장 프로퍼티를 가진 클래스가 초깃값을 할당한다.
  2. 각 클래스는 저장 프로퍼티 값을 커스터마이징할 수 있다.

부모-자식 클래스 간의 위계를 지키면서 초기화를 안전하게 할 수 있다. 스위프트는 세이프티를 네 단계 확인한다.

  1. 지정된 이니셜라이저를 통해 클래스 내 모든 프로퍼티 값을 초기화한다.
  2. 지정된 이니셜라이저를 통해 상속한 프로퍼티에 값을 할당하기 전까지 부모 클래스의 이니셜라이저까지 딜리게이트해야 한다.
  3. 편리한 이니셜라이저가 프로퍼티 값을 할당하기 전에 다른 이니셜라이저에 딜리게이트해야 한다.
  4. 이니셜라이저는 인스턴스 메소드를 호출할 수 없고, 인스턴스 프로퍼티 값을 읽거나, 초기화 첫 번째 단계가 완료된 이후 자기 자신을 값으로 참조할 수 없다.

1단계 초기화

클래스엣거 지정 또는 편리 이니셜라이저가 호출되면 새로운 인스턴스용 메모리가 할당된다. 이때 메모리는 초기화되지 않은 상태다.

지정된 이니셜라이저를 사용할 때 저장 프로퍼티 값이 모두 할당받는 게 보장된다(이때 메모리가 초기화된다). 지정된 이니셜라이저는 이때 부모 클래스 이니셜라이저를 호출해, 최상위 클래스의 저장 프로퍼티에도 동일한 작업을 진행한다. 즉 처음 지정된 이니셜라이저를 호출한 클래스가 사용(상속이든 자신의 유니크한 프로퍼티든) 모든 프로퍼티가 초기화된다.

2단계 초기화

지정된 이니셜라이저를 통해 인스턴스를 커스터마이징할 수 있다. 즉 이니셜라이저를 통해 자기 자신을 참조할 수 있고 프로퍼티 값을 바꾸거나 인스턴스 메소드를 호출할 수 있다. 편리한 이니셜라이저 또한 커스터마이징에 사용한다. 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()이 자동 사용되고 있다.

하위 클래스는 상속받은 변수 프로퍼티를 바꿀 수 있지만 상수 프로퍼티는 바꿀 수 없다는 점도 확인하자.

profile
JUST DO IT

0개의 댓글