💡익스텐션 (Extension)
익스텐션은 스위프트의 강력한 기능 중 하나로 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있습니다.
기능을 추가하려는 타입을 구현한 소스 코드를 알지 못하거나 볼 수 없다 해도, 타입만 안다면 그 타입의 기능을 확장할 수도 있습니다.
📍스위프트의 익스텐션이 타입에 추가할 수 있는 기능
- 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
- 타입 메서드 / 인스턴스 메서드
- 이니셜라이저
- 서브스크립트
- 중첩 타입
- 특정 프로토콜을 준수할 수 있도록 기능 추가
⭐️익스텐션은 타입에 새로운 기능을 추가할 수는 있지만, 기존에 존재하는 기능을 재정의할 수는 없습니다.
🔥 상속 VS 익스텐션
| 상속 | 익스텐션 | |
| 확장 | 수직 확장 | 수평 확장 |
| 사용 | 클래스 타입에서만 사용 | 클래스, 구조체, 프로토콜, 제네릭 등 모든 타입에서 사용 |
| 재정의 | 재정의 가능 | 재정의 불가 |
📌수직 확장이란?
특정 타입을 물려받아 하나의 새로운 타입을 정의하고 추가 기능을 구현하는 것
📌수평 확장이란?
기존의 타입에 기능을 추가하는 것
여기서 잠깐!!✋
" 왜 굳이 익스텐션을 써야하지? 원래 타입을 정의한 소스에 기능을 추가하면 안되나? "
이 질문에 대한 답을 생각해볼까요?🧐
.
.
.
당연히! 원래 타입을 정의한 소스에 기능을 추가해도 됩니다!
다만, 외부 라이브러리나 프레임워크를 가져다 사용할때 원본 소스를 수정할 수 없습니다.
이처럼 외부에서 가져온 타입에 내가 원하는 기능을 추가하고자 할 때 익스텐션을 사용하면 쉽게 추가할 수 있습니다~!!
🔥익스텐션 문법
익스텐션은 extension 키워드를 사용하여 선언합니다.
extension 확장할 타입 이름 {
// 타입에 추가될 새로운 기능 구현
}
익스텐션은 기존에 존재하는 타입에 추가로 다른 프로토콜을 채택할 수 있도록 확장할 수도 있습니다.
extension 확장할 타입 이름: 프로토콜 1, 프로토콜 2, 프로토콜 3 {
// 프로토콜 요구사항 구현
}
🔥익스텐션으로 추가할 수 있는 기능
📍연산 프로퍼티
extension Int {
var isEven: Bool {
return self % 2 == 0
}
var isOdd: Bool {
return self % 2 == 1
}
}
print(1.isEven) // false
print(2.isEven) // true
print(3.isOdd) // true
print(4.isOdd) // false
var number: Int = 5
print(number.isEven) // false
print(number.isOdd) // true
위의 예제는 Int 타입에 두 개의 연산 프로퍼티를 추가한 것입니다.
익스텐션으로 연산 프로퍼티를 추가할 수는 있지만, 저장 프로퍼티는 추가할 수 없습니다.
또, 타입에 정의되어 있는 기존의 프로퍼티에 프로퍼티 감시자를 추가할 수도 없습니다.
📍메서드
extension Int {
func multiply(by n: Int) -> Int {
return self * n
}
}
print(6.multiply(by: 2)) // 12
print(7.multiply(by: 10)) // 70
number = 8
print(number.multiply(by: 2)) // 16
print(number.multiply(by: 5)) // 40
위 예제는 Int 타입에 인스턴스 메서드인 multiply(by:) 메서드를 추가한 것입니다.
📍이니셜라이저
인스턴스를 초기화할 때 인스턴스 초기화에 필요한 다양한 데이터를 전달받을 수 있도록 여러 종류의 이니셜라이저를 만들 수 있습니다.
extension String {
init(int: Int) {
self = "\(int)"
}
init(double: Double) {
self = "\(double)"
}
}
let stringFromInt: String = String(int: 100) // "100"
let stringFromDouble: String = String(double: 100.0) // "100.0"
위 예제는 String 타입에 이니셜라이저를 추가한 것입니다.
클래스 타입에서 익스텐션으로 편의 이니셜라이저는 추가할 수 있지만, 지정 이니셜라이저는 추가할 수 없습니다!
지정 이니셜라이저와 디이니셜라이저는 반드시 클래스 타입의 구현부에 위치해야 합니다.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
extension Person {
convenience init() {
self.init(name: "Unknown")
}
}
let someOne: Person = Person()
print(someOne.name) // Unknown
익스텐션으로 값 타입(열거형, 구조체 등)에 이니셜라이저를 추가했을 때, 해당 값 타입이
- 모든 저장 프로퍼티에 기본값이 있습니다.
- 타입에 기본 이니셜라이저와 멤버와이즈 이니셜라이저 외에 추가 사용자 정의 이니셜라이저가 없습니다.
이 조건을 모두 성립한다면 익스텐션으로 사용자 정의 이니셜라이저를 추가한 이후에도
해당 타입의 기본 이니셜라이저와 멤버와이즈 이니셜라이저를 호출할 수 있습니다.
이외에도 서브스크립트나 중첩 데이터 타입 등 추가해줄 수 있습니다~!
이 글은 Swift 프로그래밍 책과 야곰님의 스위프트 기초 강의를 참고하여 작성하였습니다.
'Swift' 카테고리의 다른 글
| [Swift] 프로토콜(Protocol) (0) | 2021.01.28 |
|---|---|
| [Swift] 타입캐스팅(Type Casting) (0) | 2021.01.26 |
| [Swift] 빠른 종료(Early Exit) (0) | 2021.01.22 |
| [Swift] 옵셔널 체이닝(Optional Chaining) (0) | 2021.01.22 |
| [Swift] 클로저(Closure) (0) | 2021.01.16 |