Initializer

2019-06-09
Swift

안녕하세요. 도미닉입니다.

오늘은 이니셜라이저에 대해서 알아보겠습니다.

“이니셜라이저”란?

이니셜라이저는 한글로 초기화입니다.

초기화하면 어떤 단어가 생각나시나요?

리셋, 재부팅 같은 단어가 생각납니다.

그렇습니다.

초기상태로 셋팅해주는 것을 초기화라고 합니다.

스위프트에서 “이니셜라이저”란?

구조체와 클래스을 활용하고자 한다면 초기화해주어야 합니다.

이니셜라이저는 새로운 인스턴스를 만들어주는 과정이라고 할 수 있습니다.

이니셜라이저라는 작업을 통해 스위프트는 구조체와 클래스에 메모리를 할당하여 인스턴스로 만들어줍니다.

스위프트에서는 모든 프로퍼티(속성)에 값이 할당되어야 정상적으로 초기화가 되었다고 인식하며 하나의 프로퍼티라도 값이 할당되지 않았다면 오류가 발생합니다.

구조체의 이니셜라이저

구조체를 선언하면 자동으로 생성되는 이니셜라이저들과 직접 구현하는 사용자 지정 이니셜라이저, 실패할 수 있는 이니셜라이저까지 3가지 이니셜라이저를 사용할 수 있습니다.

구조체 - 자동으로 생성되는 이니셜라이저(Default Initializers)

자동 생성 이니셜라이저에는 아래와 같은 이니셜라이저들이 있습니다.

  • 기본 이니셜라이저(Default Initializer)
  • 멤버와이즈 이니셜라이저(Memberwise Initializers)

먼저 기본 이니셜라이저에 대해 알아보겠습니다.

만약 옵셔널 타입이 아닌 모든 저장 프로퍼티에 초기값이 설정되있다면 기본 이니셜라이저를 사용할 수 있습니다.

tv 인스턴스를 초기화할 때 TV 구조체의 기본 이니셜라이저를 사용했습니다.

tv 인스턴스가 생성이 되면 channel 저장 프로퍼티에 초기값인 1이 저장됩니다.

옵셔널이 아닌 모든 저장 프로퍼티에 값이 할당되어있기 때문에 정상적으로 초기화가 되었습니다.

이번에는 멤버와이즈 이니셜라이저(Memberwise Initializers) 에 대해 알아보겠습니다.

모든 저장 프로퍼티의 이름과 할당할 값을 매개변수로 넣으면서 초기화하는 것입니다.

TV 의 모든 저장 프로퍼티인 channel 을 매개변수로 초기화합니다.

이렇게 초기화를 하면 channel 저장 프로퍼티에 기본값인 1이 아니라 15가 저장됩니다.

구조체 - 사용자 지정 이니셜라이저

위에 기본으로 제공되는 이니셜라이저가 아니라 직접 기능들을 구현해 만들 수 있는 사용자 지정 이니셜라이저가 있습니다.

사용자 지정 이니셜라이저를 선언한 경우 위에서 설명한 자동으로 생성되는 이니셜라이저들은 사용할 수 없습니다.

위에 소스는 기본 이니셜라이저 중 멤버와이즈 이니셜라이즈와 동일하게 동작하는 사용자 지정 이니셜라이저입니다.

이번 예제 또한 channel 만 매개변수로 받지만 brand 저장 프로퍼티에 “LG” 를 저장하도록 구현해놓았습니다.

모든 저장 프로퍼티에 값이 들어갔고 정상적으로 초기화가 됩니다.

선언한 이니셜라이저에게 초기화를 위임하는 위임 이니셜라이저도 있습니다.

위에서 init() 은 self.init 을 통해 위에서 선언한 init(channel: Int) 에게 초기화를 위임합니다.

구조체 - 실패할 수 있는 이니셜라이저

꼭 성공하지 않아도 된다면 실패할 수 있는 이니셜라이저를 사용할 수 있습니다.

꼭 인스턴스가 생성되는 것이 아니라 nil이 반환될 수 있습니다.

animal 변수에는 실패했기 때문에 nil이 저장되며 animal 의 타입은 Animal?(옵셔널) 입니다.

클래스의 이니셜라이저

지정 이니셜라이저편의 이니셜라이저, 실패할 수 있는 이니셜라이저, 필수 이니셜라이저까지 4가지 이니셜라이저를 사용할 수 있습니다.

클래스 - 지정 이니셜라이저(designated initializer)

지정 이니셜라이저는 구조체의 사용자 지정 이니셜라이저와 유사합니다.

위와 같이 할당되지 않은 저장 프로퍼티가 없도록 init 을 선언해주는 것이 지정 이니셜라이저입니다.
클래스를 상속했을 때 이니셜라이저는 아래와 같은 규칙을 지켜야합니다.

자식 클래스의 지정 이니셜라이즈는 부모 클래스의 지정 이니셜라이저를 호출해야만 합니다.

위에 예제에 Square 클래스의 지정 이니셜라이저는 부모 클래스인 Shape 의 지정 이니셜라이저(super.init)를 호출해야만 합니다.

자식 클래스의 모든 저장 프로퍼티에 값이 할당된 후에 부모 클래스의 지정 이니셜라이저를 호출해야 합니다.

위에 예제에 Square 클래스의 sideLength 저장 프로퍼티에 값을 할당한 후에 super.init 을 호출해야만 합니다.

자식 클래스에 저장 프로퍼티가 없어서 지정 이니셜라이저가 선언되지 않았다면 부모 클래스의 지정 이니셜라이저가 상속됩니다.

위에 예제에 Square 에 저장 프로퍼티가 없기 때문에 지정 이니셜라이저를 선언하지 않을 수 있었습니다.
이러한 경우 부모 클래스의 지정 이니셜라이저가 상속됩니다.

클래스 - 편의 이니셜라이저(convenience initializer)

편의 이니셜라이저는 구조체의 이니셜라이저 위임과 유사한 점이 있습니다.

필요에 따라 매개변수를 다르게 해서 지정 이니셜라이저를 호출하여 초기화하는 방법입니다.

편의 이니셜라이저는 무조건 자신의 지정 이니셜라이저를 호출해야 합니다.

convenience init 은 self.init 으로 자신의 지정 이니셜라이저를 호출하고 있습니다.

부모 클래스의 모든 지정 이니셜라이저를 오버라이딩해준 경우 부모의 편의 이니셜라이저들도 상속됩니다.
위에 예제에서 RecipeIngredient 클래스는 부모 클래스의 지정 이니셜라이저init(name: String) 을 오버라이딩합니다.

위에 규칙을 지켰기 때문에 RecipeIngredient 클래스는 부모 클래스의 편의 이니셜라이저 init() 을 상속 받았습니다.

oneMysteryItem 인스턴스는 정상적으로 생성됩니다.

클래스 - 실패할 수 있는 이니셜라이저(Failable Initializer)

클래스에서도 실패할 수 있는 이니셜라이저를 만들 수 있습니다.

anmail 은 nil 이 할당되며 타입은 Animal?(옵셔널)입니다.

클래스 - 필수 이니셜라이저(Required Initializer)

부모 클래스에서 필수 이니셜라이저를 선언해주면 자식 클래스들에서 무조건 필수 이니셜라이저를 구현해주어야 합니다.

정리

구조체와 클래스의 이니셜라이저에 대해서 알아봤습니다.

잘못된 내용이나 궁금하신 점은 댓글 부탁드립니다.

감사합니다.