-
Swift - ExtensionProgramming/Swift 2021. 12. 20. 18:39
안녕하세요 BeePeach입니다 :/
이번에 공부해볼 내용은 extension입니다.
Extension은 이미 존재하는 class, struct, enum, protocol
즉, 다시 말해 존재하는 Type에 새로운 멤버를 추가시킬 때 사용합니다.
심지어 우리가 코드에 접근할 수 없는 기본 제공 Type(Int, String 등등...) 또는 OpenSource에서 제공하는 Type에도 멤버를 추가시킬 수 있습니다.
여기서 주의 깊게 봐야할 단어는 이미 존재하는과 새로운 멤버입니다.
존재하지 않는 Type에는 extension을 사용할 수 없습니다.
그리고 새로운 멤버를 추가시키는 것이지 이미 존재하는 멤버를 수정하는 게 아니므로 override도 불가능합니다.
Extension으로 추가할 수 있는 기능들은 다음과 같습니다.
- Computed instance property, Computed type property
- Instance method, Type method
- Convenience Initializer
- Subscript
- Nested Type
- Protocol comform
Syntax
문법은 extension 키워드를 사용합니다. 그리고 확장시키고 싶은 Type의 이름을 적어줍니다.
그리고 원하는 멤버를 추가시키면 됩니다.
Type이 이미 존재하는 protocol을 extension으로 채용하도록 하고 싶다면 Type뒤에 protocolName을 적어주고 코드를 구현하면 됩니다.
그럼 각각 멤버들을 추가시키는 방법에 대해서 자세히 보도록 하겠습니다.
Property
Extension은 property 중에서 computed property만 확장이 가능합니다. Stored property는 추가시킬 수 없습니다.
그럼 자주 사용하게 되는 예시로 Date type을 확장시켜서 data 인스턴스의 연도를 리턴해주는 computed property를 구현해보도록 하겠습니다.
Date에서 바로 년도를 추출하는 방법은 없습니다.
Calendar를 통해서 원하는 component를 추출해야 합니다. 해당 날짜의 연도를 얻을 때마다 매번 calendar를 선언하고 component(_:from:) 메서드를 이용하는 방법은 효율적이지 못합니다.
그래서 extension으로 Date type을 확장시켜 year이라는 computed instance property를 추가시켰습니다.
그러면 이제 date에서 바로 year를 얻어올 수 있게 됐습니다.
만약 Computed type property를 추가시키고 싶다면 static이나 class 키워드를 추가하고 선언해주면 됩니다.
위에서 Stored property는 추가시킬 수 없다고 했죠??
한번 추가시켜보도록 하겠습니다.
Double type에 pi라는 stored instance property를 추가시켜보려 했습니다.
하지만 extension은 stored property를 가질 수 없다고 나오네요.
(여담으로 사실 Double에는 pi라는 type property가 이미 구현되어 있습니다.)
Method
Extension을 이용하여 Instance method, Type method를 추가시킬 수 있습니다.
제약 사항은 존재하지 않습니다.
struct나 enum method에서 인스턴스 값을 변경할 때 붙여주던 mutating 키워드도 똑같이 붙여주면 됩니다.
Instance method의 예제부터 살펴보겠습니다.
이번에도 Date를 확장시켜봤습니다.
매번 DateFormatter을 이용하여 string으로 변환시키는 것이 귀찮아서 메서드를 하나 정의했습니다.
다른 점은 extension 블록 안에서 정의한 것뿐 기존에 struct에서 구현한 것과 다른 점이 하나도 없습니다.
그럼 이번에는 type method를 구현해보도록 하겠습니다.
class나 static 키워드를 사용하면 됩니다.
그냥 type method는 너무 쉬우니 연산자를 추가시켰습니다.
연산자를 정의할 때는 type method로 정의하게 됩니다. (혹시 연산자 정의 방법을 모르신다면 custom operator에 대해서 공부해보세요! 포스팅 한 줄 알았는데 넘어갔네요... 다음에 작성하도록 하겠습니다.)
Initializer
Extension을 이용하면 init도 확장할 수 있습니다.
Value type의 init은 크게 상관 없지만 Reference type의 init은 designated init과 convenience init으로 나뉘어 있죠??
Reference type의 init은 convenience init만 확장이 가능합니다.
Designated init과 deinitializer는 반드시 원래 class에서 구현해야 합니다.
그럼 한 번 class에서 designated init을 확장시켜보도록 하겠습니다.
UIColor는 class로 구현되어 있습니다.
RGB를 이용하여 새로운 UIColor 인스턴스를 생성하는 designated init을 구현해보았습니다.
그랬더니 extension에는 designated init을 구현할 수 없다는 에러가 발생합니다.
Convenience init으로 변경해주니 에러가 사라졌습니다.
기존에는 RGB 값을 0.0부터 1.0사이의 값을 전달해 줘야하는데 우리는 주로 0 부터 255 값을 사용하기 때문에 이를 지원해주는 init을 추가시켜준 것입니다.
Subscript
Subscript도 기본 구현과 똑같이 구현하면 됩니다.
바로 예시를 보겠습니다.
기본적으로 제공하는 String의 subscript는 String.Index를 이용합니다.
그래서 바로 Int를 적용시키면 에러가 발생하게 됩니다. 그래서 이 부분을 쉽게 사용하기 위해서 String을 extension 시켰습니다.
Confirm Protocol
Protocol을 채용할 때 extension을 이용할 수 있습니다.
이 부분은 이미 iOS에서 많이 사용하고 있었을 텐데요.
TableView, CollectionView Delegate와 같이 class내부에 구현해도 되지만 가독성을 위해서 extension을 이용해서 delegate나 datasource를 채용하는 경험을 해보셨을 겁니다.
이렇게 사용할 수 있습니다.
Nested Type
Type안에 nested type도 extension으로 추가시킬 수 있습니다.
Int를 확장시켜 enum Kind를 추가시켰습니다.
그리고 kind라는 computed property도 추가시켜서 해당 인스턴스가 양수인지 음수인지 0인지 판단하도록 했습니다.
참고자료
여러분의 새로운 도전을 응원합니다 | KxCoding
Mastering SwiftUI 더 적은 코드로, 더 멋진 UI 만들기
kxcoding.com
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
Extensions — The Swift Programming Language (Swift 5.6)
Extensions Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you don’t have access to the original source code (known as retroactive modeling). Extensions
docs.swift.org
728x90'Programming > Swift' 카테고리의 다른 글
Swift - Protocol Initializer , Subscript (0) 2021.12.28 Swift - Protocol (0) 2021.12.22 Swift - Deinitializer (0) 2021.12.19 Swift - Required Initializer (0) 2021.12.18 Swift - Failable InitialIzer (0) 2021.12.17