Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] struct에서 convenience init 키워드 없어도 init에서 다른 init을 호출할 수 있는 이유 (#memberwise init, #designated init, #convenience init) 본문

iOS 응용 (swift)

[iOS - swift] struct에서 convenience init 키워드 없어도 init에서 다른 init을 호출할 수 있는 이유 (#memberwise init, #designated init, #convenience init)

jake-kim 2023. 8. 6. 01:29

기초 지식) 초기화의 종류

  • 1) memberwise init (struct only)
    • struct에서 제공하는 초기화 방법이며, struct의 모든 property에 대해서 자동으로 internal 접근 제한자인 초기화가 생성
struct Person {
    var name: String
    var age: Int
}

let person = Person(name: "jake", age: 30)
  • 2) designated init (class only)
    • 해당 클래스에 의해 선언된 모든 property를 모두 초기화하고 적절한 super class의 init을 호출하여 super class까지 init 프로세스를 진행
    • Designated init은 그냥 "Designated"를 생략하여 그냥 init으로 사용
class Person {
    let name: String
    let age: Int
    let birthDay: String

    init(name: String, age: Int, birthDay: String) {
        self.name = name
        self.age = age
        self.birthDay = birthDay
    }
}
  • 3) convenience init (class only)
    • Designated init의 parameter중 일부를 기본값으로 설정하여 동일한 클래스에서 지정된 initializer를 호출하도록 정의
class Person {
    let name: String
    let age: Int
    let birthDay: String

    init(name: String, age: Int, birthDay: String) {
        self.name = name
        self.age = age
        self.birthDay = birthDay
    }

    convenience init(age: Int, birthDay: String) {
        self.init(name: "홍길동", age: age, birthDay: birthDay)
    }
}

// convenience init 사용
let person = Person(age: 12, birthDay: "121212")

struct에서 init 개념

  • struct에서는 convenience init 키워드를 사용하지 않고 그냥 init키워드를 사용해도 마치 class의 convenience init처럼 초기화가 가능
struct MyStruct {
    let age: Int
    let name: String
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    // class의 convenience init처럼 동작이 가능
    init(age: Int) {
        self.init(age: age, name: "jake")
    }
}
  • class에서는 위처럼 convenience을 붙이지 않으면 컴파일 에러가 발생

struct는 convenience 초기화 없이도 self.init()접근이 가능한 이유

  • struct는 상속을 할 수 없고 class는 상속을 할 수 있기 때문에 class에서는 designated init안에서 또다른 designated init을 호출할 수 없도록 설계
  • swift 공식 문서를 보면 아래 그림과 같이 sub class에서 초기화가 시작되면 super class에도 하나씩 타고 순서대로 초기화가 진행

  • 만약 class에서 convenience없이 designated init안에서 또다른 designated init이 호출된다면 designated init이 두번 호출될 위험이 있고 이렇게 된다면 property가 두 번 이상 초기화될 위험이 있기 때문에 swift 내부적으로 convenience를 붙여야 init안에서 또다른 init을 호출 할 수 있도록 컴파일 에러가 발생시키도록 한 것

* 전체 코드: https://github.com/JK0369/ExStructInit

* 참고

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/

https://ios-development.tistory.com/542

Comments