본문 바로가기
iOS/Swift

[Swift] super.init()은 언제 호출해야할까

by 0inn 2022. 11. 29.

오늘은 헷갈렸던 super.init() 호출 시점에 대해 공부하고자 합니다.

개발을 하다보면 super.init()을 어느 시점에 작성하는지에 따라 오류가 나곤합니다.

왜인지, 언제 호출해야하는지 알아봅시다 ~!

공부하고 적는 글이므로 오류가 있을 수 있습니다 . . 

 

먼저 생성자와 상속에 대해 알아야 합니다.

상속하는 과정에서 자식의 init()에서 super.init()이 호출되기 때문입니다.

생성자

간단하게 생성자는 특정 타입의 새로운 인스턴스를 생성하는 것입니다.

 

init() {
	// 초기화 수행
}

 

init()에 파라미터가 존재할 수도 있습니다.

상속

상속이란 간단하게 부모 클래스로부터 메서드, 프로퍼티 및 기타 등등을 상속받는 것을 뜻합니다.

즉, 부모 클래스를 상속받은 자식클래스는 부모 클래스의 멤버를 모두 가지면서 자식 클래스에 필요한 멤버들을 더 추가한 새로운 클래스라고 할 수 있습니다.

그렇기 때문에 BaseVC나 BaseView를 만들어놓고, 각각의 상속받아 NewVC나 NewView를 구현하곤 합니다.

 

예시를 들어볼게요.

제가 구현했던 roundChartView의 일부입니다.

여기서 roundChartView는 BaseView를 상속받고 있습니다.

 

// MARK: - Properties

var percent: Int
var lineWidth: CGFloat
var radius: CGFloat

// MARK: - Initializer

init(percent: Int, lineWidth: CGFloat, radius: CGFloat) {
    self.percent = percent
    self.lineWidth = lineWidth
    self.radius = radius
    
    super.init(frame: .zero)
}

// MARK: - Methods

func setupProperty() {
    backgroundColor = .systemBackground
}

 

여기서 super.init()을 찾을 수 있는데요.

super.init()

일단 super는 자신의 부모 클래스를 가르킵니다.

super.init()이란 자신의 부모 클래스의 생성자를 의미하겠죠.

 

현재 위 예시 코드는 roundChartView -> BaseView -> UIView 의 형태로 상속받고 있습니다.

최상단 부모클래스의 init()부터 살펴볼게요.

 

// MARK: - UIView
public init(frame: CGRect)

// MARK: - BaseView
override init(frame: CGRect) {
    super.init(frame: frame)
}

// MARK: - roundChartView
init(percent: Int, lineWidth: CGFloat, radius: CGFloat) {
    self.percent = percent
    self.lineWidth = lineWidth
    self.radius = radius
    
    super.init(frame: .zero)
}

 

super.init()으로 부모 클래스들을 init()해줘야 인스턴스가 생성되고 모든 함수 및 코드가 실행가능하게 되겠죠.

 

그렇다면 이 super.init()은 언제 호출해야 할까요 ?

 

내부 프로퍼티를 모두 초기화한 후

 

 

위와 같이 내부 property 초기화 전에 super.init()을 호출하면 에러가 납니다.

 

그 이유가 뭘까요 ?

사실 initialization의 개념만 알고 있다면 당연한 사실입니다.

Swift 공식 문서를 보면 이와 같은 설명이 있습니다.

Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that’s required before the new instance is ready for use.

 

즉, 객체의 메모리 크기는 모든 stored properties의 크기를 통해 결정되는데 초기화 작업이 부모 클래스 방향으로 이뤄지고, 마지막 작업이 가장 위에 있는 최상단 부모클래스에서 끝나게 됩니다.

그렇기 때문에 자식 클래스의 메모리 크기를 부모클래스로 가기 전에 알고 있어야 하는 것이죠 !

 

메소드 호출 전 (self. 호출 전)

 

 

이렇듯 self.를 호출하는 경우 에러가 발생합니다.

그 이유는 위를 바탕으로 알 수 있는데 init 함수를 통해 초기화 작업을 해줘야 인스턴스가 생성되는데 super.init() 전에는 인스턴스가 생성되기 전이므로 self.메서드() 호출이 불가능하도록 제한한 것입니다.

 

정리

- super.init()은 상속받을 때 init()에서 호출

- super.init() 호출 시점은 내부 프로퍼티 초기화 후 & self. 호출 전

 

단순하게 에러 뜨면 읽고 바꾸곤 했는데요.

앞으론 모든 것에 이유를 찾고 꼼꼼히 공부하고자 합니다. (가장 중요한 자세라고 생각합니다 . . 그동안 너무 놓쳤어요 . . ㅠ)

끝 ! !

'iOS > Swift' 카테고리의 다른 글

[Swift] stride 함수 / Set  (0) 2022.10.25
[Swift] Swift 알고리즘 - 수학  (0) 2022.10.13
[Swift] Swift 알고리즘 - Dictionary  (0) 2022.10.12
[Swift] Swift 알고리즘 - 문자열 / 배열  (0) 2022.10.11
[Swift] 클로저 (Closure)  (0) 2022.09.24