article thumbnail image
Published 2022. 11. 9. 18:56

Swift에서 initializer란 객체를 초기화 하는것으로 

initializer가 끝나게 되면, 저장 프로퍼티가 모두 값을 가지고 있어야 한다.

또한, Swift에서의 initializer는 값을 return 하지 않는다! 

 

Default Initializer 

Default initializer란, parameter로 아무것도 전달하지 않는 Initializer이다. 

만약, 객체의 모든 저장 프로퍼티가 값을 가지는 경우 default initializer가 제공이 된다. 

class A {
    var num: Int
    init(){ 
        self.num = 10
    }
    
}

class B {
    var num: Int?
    let num2 = 10
}

let a = A() //구현한 default initializer
let b = B() //제공되는 default initializer

Optional 타입의 var 저장 프로퍼티의 경우 nil값으로 초기화 된다.(let은 불가능)

 

 

Struct Initializer

Swift에선,

Class는 initializer의 구현을 요구하지만,(모든 저장 프로퍼티가 초기값을 갖지 않는 경우)

Struct에서는 구현하지 않아도 된다. 

그 이유는 StructMemberwise initializer를 제공하기 때문이다.

 

struct A {
    var num1: Int
    var num2: Int
}

let a = A(num1: 1, num2: 2)
//제공된 Memberwise initializer를 이용한 초기화

 

Memberwise initializerstruct안에 initializer함수를 직접 구현하지 않는 경우에만 사용이 가능하지만,

extension으로 구현해주게 되면 Memberwise initializer 사용이 가능하다.

struct A {
    var num1: Int
    var num2: Int
}

extension A {
    init(num1: Int){
        self.num1 = num1
        self.num2 = 20
    }
}

let a = A(num1: 1, num2: 2)

 

Class Initializer

class는 저장 프로퍼티가 초기화 되지 않는 경우! 

initializer를 직접 구현해주어야 한다. (즉, Memberwise Initializer를 제공하지 않는다)

 

클래스의 initializer는 크게 2가지로 나뉘게 되는데,

designated Initializerconvenience initializer이다.

 

designated initializer모든 저장 프로퍼티를 초기화 하는 initializer이다.

쉽게, 말해서 초기화가 되지 않은 저장 프로퍼티를 초기화 하는 initializer이다. 

class A {
    var num: Int
    var num2 = 10
    
    init(num: Int) {
        self.num = num
    }
}

class B:A {
	var num3: Int
    
    init(num:Int, num3: Int) {
    	self.num3 = num3
        super.init(num: num) //super class의 initializer호출
    }
}

상속을 한경우에는 해당 class의 초기화가 끝나고, super class의 designated initializer를 호출 하여야 한다.

 

 

 

반면, Convenience Initializer는 모든 저장 프로퍼티를 초기화 하지 않는다!

이 Convenience Initializer는 사용하기 위한 몇가지 규칙이 있다. 

  • 같은 클래스 내의 다른 initializer를 호출하여야 한다. 
  • 최종적으로는 Designated Initializer를 호출하여 모든 저장 프로퍼티의 초기화를 진행한다
class A {
    var num: Int
    var num2 = 10
    
    //designated Initializer
    init(num: Int) {
        self.num = num
    }
    
    //convenience Initializer
    convenience init(number: Int){
        self.init(num: number)
    }
    
    convenience init() {
        self.init(number: 100)
    }
}

convenience init() 은 convenience init(number: Int) 를 호출하고 

convenience init(number: Int)은 최종적으로 init(num: Int) 를 호출한다. 

 

Failable Initializer

앞에서의 Initializer는 모두 성공을 염두해 두고 구현한 Initializer였다.

Failable Initializer초기화에 실패할시 nil을 return함으로써 실패를 명시할 수 있다. 

init? 을 사용하여 사용할 수 있다.

class Person {
    var age: Int
    init?(age: Int){
        if(age < 0 || age > 120) {
            return nil
        }
        else {
            self.age = age
        }
    }
}

성공할 시에는 return을 사용하지 않는다! 

 

 

앞서, Swift는 initalizer는 어떠한 value을 리턴하지 않는다고 하였지만, 

여기선 nil을 리턴하기에 헷갈려서 swift 공식문서를 찾아보았다.

Initializers는 value을 리턴하지 않고, self의 initialization이 끝날때 완벽하게 초기화 되게 해준다. 

따라서, initialization의 실패를 return nil 로 알리지만, 초기화 성공을 알리기 위해 return keyword를 사용하지 않는다.

 

 

 

Required initializer 

required initializer란! 해당 객체를 상속하는 모든 객체(sub class)들에게 해당 Initializer를 Override 하라는 키워드다.

 

상속하는 객체들은 Initializer를 override 키워드가 아닌!

required 키워드를 통해 오버라이드 한다. (즉, required에는 override 가 내포되어 있다.)

쉽게 생각해서, 서브 클래스에서 반드시 오버라이드 해야하는 initializer이다.

class Person {
    var age: Int
    
    required init(age: Int) {
        self.age = age
    }
}

class Student: Person {
    var school: String
    
    init(age: Int, school: String){
        self.school = school
        super.init(age: 10)
    }
    
    required init(age: Int) {
        self.school = "default"
        super.init(age: age)
    }
}

이와 같이 subclass에서 init은 생략이 가능하지만, required init은 반드시 구현해주어야 한다.

 

 

Reference

initialization

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

[Swift] Initializer(3) - required init?(coder:)  (1) 2022.11.10
[Swift] Initializer(2) - Class Initializer의 상속  (0) 2022.11.10
[Swift] KVO, Delegate and Notification  (2) 2022.10.08
[Swift] Notification  (0) 2022.10.08
[Swift] Delegate  (0) 2022.10.07
복사했습니다!