-
Swift - Protocol Initializer , SubscriptProgramming/Swift 2021. 12. 28. 18:28
안녕하세요 BeePeach입니다 :)
이번 포스팅에서는 지난번 포스팅에 이어 Protocol에서 Initializer와 Subscript를 정의하는 방법에 대해서 공부해보도록 하겠습니다.
Initializer
Init을 정의하는 방법도 마찬가지로 body를 제외하고 헤더만 적어주면 됩니다.
어려울 게 없으니 바로 예시를 보겠습니다.
Figure라는 프로토콜에 name 프로퍼티와 init(name:)을 정의했습니다.
그리고 Triangle이라는 struct를 정의했는데요 init(name:)을 요구하고 있으니 init(name:)을 정의하고 내부 구현은 우리가 원하는 대로 할 수 있습니다.
이 코드에서 짚고 넘어갈 부분은 protocol에서 name 프로퍼티와 init(name:)을 요구하고 있고 Triangle은 구조체이므로 name프로퍼티만 선언해주면 Memberwise initiailizer로 init(name:)이 자동으로 제공되죠?? 그래서 init(name:)을 생략해도 protocol 요구사항을 만족하지 못했다는 에러가 발생하지 않습니다.
init(name:)을 생략해도 에러가 발생하지 않죠?? 이렇게 init이 자동으로 생성된것도 protocol 요구사항을 만족한 것으로 취급합니다.
Struct는 상속이 없으므로 init을 정의하는게 쉽고 Class는 상속으로 인해 init의 구현이 복잡했던 게 기억나시나요??
(기억이 안나신다면 여기를 참고해주세요.)
Protocol의 init 요구사항을 class에서 만족시키려면 어떻게 해야 할까요???
Designated, Convenience 등등 다 구별을 해줘야 할까요???
정답은 바로 그렇지 않습니다! 입니다.
Protocol의 요구사항을 만족시킬 init을 구현할 때 designated init인지 convenience init인지 전혀 중요하지 않습니다.
둘 중 무엇을 쓰던 상관없습니다. 그냥 Protocol에서 정의한 파라미터만 지켜주면 됩니다.
하지만 한 가지 추가해야 하는 게 있는데요.
바로 required 키워드입니다.
Required init은 반드시 subclass에서 구현을 해야 했죠??
Class에는 상속이 존재하고 protocol에서 요구하는 init을 구현하기 위해서는 required 키워드를 사용해서 혹시 존재하게 될 subclass에서도 반드시 protocol 요구 init을 구현하도록 명시해줘야 합니다.
백문이불여일견 바로 작성해보면 되겠죠??
넵 바로 required를 붙이라는 에러가 나오는 것을 확인할 수 있습니다.
이렇게 requried만 붙여주면 해결이 됩니다.
그리고 Elipse class는 Circle을 상속하고 있습니다. Circle에서는 이미 Figure protocol을 채용하고 있죠??
그래서 Elipse에서는 Figure를 또 적어주지 않습니다. Circle을 상속하면 자동적으로 Figure를 채용하게 됩니다.
그렇기 때문에 Elipse에서 init(name:)을 또 구현해준 것을 확인할 수 있습니다. 이때도 required 키워드는 꼭 작성해야 합니다.
그럼 몇 가지 주의해야 할 예시를 또 보도록 하겠습니다.
만약 subClass에서 프로토콜의 요구 init을 구현하려고 했는데 superClass에서 먼저 작성이 되어있다면 override를 해야겠죠??
그때는 override와 required를 같이 적어줍니다. 둘의 순서는 상관없습니다. 두 키워드가 모두 들어가기만 하면 됩니다.
주의하실 점은 required init은 override 키워드를 작성하지 않는다면서?!?라고 생각하실 수 있는데 프로토콜을 채용할 때는 조금 달라집니다. override 키워드를 작성하지 않는 경우는 위의 Circler과 Elipse의 경우입니다.
두 경우를 헷갈리기 쉬운데 정확하게 기억하지 못해도 Error을 알아서 잘 알려주기 때문에 큰 걱정하실 필요는 없습니다.
Protocol의 요구 init을 구현하는데 required를 붙이지 않아도 되는 경우가 1가지 있습니다.
required를 요구하는 이유가 'Class에는 상속이 존재하고 protocol에서 요구하는 init을 구현하기 위해서는 required 키워드를 사용해서 혹시 존재하게 될 subclass에서도 반드시 protocol 요구 init을 구현하도록 명시해줘야 합니다.'라고 설명했었죠???
그럼 만약 subclass가 절대 존재할 이유가 없다면? 그럼 required가 필요 없겠죠??
required 키워드가 없어도 에러가 나지 않는 것을 확인할 수 있습니다.
Failable Initializer
Protocol에서 init을 정의할 때 non-failable init만 정의가 가능한 게 아니라 failable init도 정의가 가능합니다.
구현 방식은 init과 똑같이 body는 생략해줍니다. 대신 ?과 !가 포함됩니다.
나머지는 다를 게 없습니다.
그럼 바로 예시를 보도록 하겠습니다.
Failable이라는 프로토콜에는 init?(name:)이 정의되어 있습니다.
그렇다면 이 프로토콜을 채용하는 type에서는 init?(name:)을 구현해야겠죠??
Desk에서는 그대로 init?(name:)을 구현했습니다.
그런데 Chair에서는 init(name:)을 구현했습니다. 그래도 에러가 나지 않았네요??
Protocol의 요구 failable init은 non-failable init 또는 failable init으로 만족시키면 됩니다.
Failable init은 성공할 수 도 실패할 수 도 있으므로 무조건 성공한다 해서 문제가 될 건 없잖아요??
하지만 반대의 경우는 다릅니다.
Protocl에 non-failable init으로 정의되어 있는 경우에는 반드시 non-failable init으로 구현을 해줘야 합니다.
Non-Failable init은 반드시 초기화가 완료돼야 하기 때문에 실패란 존재하면 안 되기 때문입니다.
Subscript
Protocol에서 Subscript를 정의할 때도 마찬가지로 구현 부분은 생략합니다.
Subscript를 구현할 때 getter setter를 구분해줬던 게 기억나시나요??
Protocol에서 정의할 때는 헤더 부분은 똑같지만 body에는 프로퍼티와 비슷하게 get과 set을 작성합니다.
간단한 예시를 보도록 하겠습니다.
크게 의미 있는 코드는 아닙니다.
Indexable이라는 Protocol에 subscript가 정의되어 있습니다.
Protocol에 정의가 된 것처럼 파라미터와 returnType을 지켜서 CustomData에 subscript를 구현했습니다.
그리고 요구사항은 { get }으로 돼있지만 최소 요구사항 이므로 setter를 추가시켜줘도 문제가 없는 것을 확인할 수 있습니다.
참고자료
여러분의 새로운 도전을 응원합니다 | KxCoding
Mastering SwiftUI 더 적은 코드로, 더 멋진 UI 만들기
kxcoding.com
https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
Protocols — The Swift Programming Language (Swift 5.6)
Protocols A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of tho
docs.swift.org
728x90'Programming > Swift' 카테고리의 다른 글
Swift - Protocol Inheritance (0) 2022.01.02 Swift - Protocol as Type (0) 2021.12.29 Swift - Protocol (0) 2021.12.22 Swift - Extension (0) 2021.12.20 Swift - Deinitializer (0) 2021.12.19