스위프트에는 여러종류의 init이 있다는거 알고계셧나요?
객체를 생성할 때 제공되는 함수를 말하구요
생성자를 통해서 객체를 생성할 때 원하는 값을 설정해서 만들 수가 있어요
- designated init
- custom init
- default init
- convenience init
- required init
- failable init
- memberwise init
이제부터 하나하나 위에서 언급한 init을 알아볼게요
designated init
지정된 초기화라는 뜻이에요
보통 지금까지 많이 봤던 init이에요
모든 class는 적어도 1개이상 가지고 있어야해요 선언되지않으면 default init함수가 제공되요
하지만 이때 저장프로퍼티가 있는데 초기화가 안되어있다면 불가능해요
class를 만들때 변수초기화를 꼭 해줘야하잖아요?? :)
가장 기본적인 역할을 하구요
저장프로퍼티 초기화를 책임지고 있어요
custom init이기도하죠
// case1
class A {
init() { // <<- designated init
...
}
}
A() // 객체생성
// case2
class A {}
A() // default init함수적용
// case3
class A {
let a: String // 초기화 에러
}
A() // 불가능
custom init
구현한 init이에요
객체를 만들 때 받아온 값으로 초기값을 정해주는 거에요
designated init도 custom init에 속하죠
init을 새로 만들어 줄 수 있으니까요
(custom init과 designated모두 보통 init들이라고 생각하면되요)
default init
아무값도 받지않고 임의의 디폴트값으로 설정하는거에요
값을 class나 struct내에서 정해주는거에요
class A {
let a = 123 // default init
}
class A {
let a: Int
init() {
a = 123 // default init
}
}
convenience init
보조 이니셜라이저구요
다른 init에 의존적인 init이에요
중요한 기능은 다른 init에게 맡기고 자신은 특정한 일만 수행하구요
반드시 self.init을 통해 다른 init을 호출해야해요
따라서 designated init이 하나는 있어야해요
class A {
let aa: Int
init (a: Int) {
aa = a
}
init (a: Int, b: Int) {
aa = a
print(b)
}
convenience init(c: Int) {
self.init(a: 3, b: c)
}
}
여기서 그러면
init(a: Int)와
convenience init(c: Int)의 차이는 뭘까요..??
생성할때
객체를 생성하는 방식이 같네요!?!?
그러면... 코드가 다른거아닌가요..??!
위의 코드는 다르게 구현했기 때문에 다르지만
만약 init(a: Int)에서 init(c: Int)와 같은 코드를 구현하게 된다면
init(c: Int)는 어디에 쓰는걸까요...??
제 생각에는 그 class타입에만 해당되는 생성자라고 생각해요
상속을 받아도 그 init은 해당이 되지않는거죠
상속받은 class의 생성자에는 init(c: Int)가 없는게 보이시나요??
또한 convenience init은 struct(구조체) 에서는 사용할 수 없는 이니셜라이저에요!!
그렇기 때문에 해당 class에서만 사용하는 생성자임을 명시하는게 차이인것 같아요
더 찾아보니
이러한 설명이 공식문서에 설명이 잘되어있는데요( 제 가정이 다 틀리진 않은것같아요.. ㅎ )
한글로 번역된 문서에요
xho95.github.io/xcode/swift/grammar/initialization/2016/01/23/Initialization.html
이러한 규칙을 적용해야해요
간단하게 요약하자면
Convenience는 의존적인 생성자고 클래스내의 designated을 호출 해줘야해요
그래서 수평적인 호출을 하고
Designated는 상위계층이 있다면 상위init을 불러줘야하므로
수직적인 호출을 한다는 내용이에요
required init
자신을 상속하는 subclass들이 모두 따라야하는 필수 init이에요
상속받는 자식class에 init을 따로 구현해주지 않는다면 부모것을 쓰기 때문에 아무런 문제가 없지만
init을 구현한다면 required init은 꼭 구현해줘야 해요
init을 구현한다면 이렇게 에러를 볼수잇죠...
class A {
init() {
}
required init(a: Int) {
print(a)
}
}
class B: A {
override init() {
super.init()
}
required init(a: Int) {
super.init()
fatalError("init(a:) has not been implemented")
}
}
failable init
특정조건에서는 생성이 안되도록 정의해주는거에요
init옆에 ?를 붙여서 init?() 형태로 사용해요
class A {
init?(a: Int) {
if a == 0 {
return nil
}
print(a)
}
}
let a1 = A(a: 0)
let a2 = A(a: 1)
print(a1) // nil
print(a2) // Optional(A)
memberwise init
struct에만 존재하는 이니셜라이저에요
자동으로 init이 제공되는 것을 말해요
객체가 생성될때 필요한 인자들을 자동으로 요구해줘요
우선 첫번째로는 아래와 같이 프로퍼티가 있는경우
struct는 init을 안 만들어도 에러가없지만
class는 init을 만들어 줘야해요
구조체인 B는 init을 안 구현해줘도
이렇게 자동으로 만들어줘요
이 기능을 memberwise init이라고 해요
'iyOmSd > Title: iOS Think🤔' 카테고리의 다른 글
[iOS] WWDC16 Swift Performance - 성능 이해하기 (0) | 2020.10.08 |
---|---|
[iOS] UIAlertController 참조과정 (1) | 2020.09.03 |
[iOS] Swift Memory - COW (Copy On Write) (0) | 2020.08.03 |
[iOS] Swift Event - Delegate, Notification, KVO란? (3/3) (0) | 2020.03.28 |
[iOS] Swift Event - Delegate, Notification, KVO란? (2/3) (0) | 2020.03.09 |