[Swift 기초] 익스텐션
2022. 4. 5. 19:14ㆍSwift 기초 정리
728x90
//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎
익스텐션은 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있는 기능
1. 익스텐션의 특징
- 익스텐션(extension): 기존의 코드 변경 없이 기능을 추가할 수 있다.
- 익스텐션은 모든 타입에 적용할 수 있다: 구조체, 열거형, 클래스, 프로토콜, 제네릭 타입 등
- 타입만 알고 있다면 그 타입의 기능을 확장할 수 있다.
- 모든 타입에 연산 프로퍼티, 메서드, 이니셜라이저, 서브스크립트, 중첩 데이터 타입 등을 추가할 수 있다.
- 기능을 추가할 수 있지만, 기존에 존재하는 기능을 재정의 할 수 없다.
- 프로토콜과 함께 사용하면 더욱 강력
1-1. 클래스와 익스텐션 비교
상속 | 익스텐션 | |
확장 | 수직확장 | 수평확장 |
사용 | 클래스타입 | 클래스, 구조체, 프로토콜, 제네릭 등 모든 타입 |
재정의 | 가능 | 불가능 |
- 클래스의 상속은 특정타입을 물려받아 하나의 새로운 타입을 정의하고 추가 기능을 구현하는 수직확장
- 익스텐션은 기존의 타입에 기능을 추가하는 수평 확장
- 스위프트 표준 라이브러리에 정의되어 있는 타입은 실제 구현 코드를 수정할 수 없다.
- 상속을 받으면 기존 기능을 재정의할 수 있다.
- 익스텐션은 재정의 할 수 없다.
2. extesion: 익스텐션
extension 확장할 타입 이름 {
/* 타입에 추가될 새로운 기능 구현*/
}
//ex
extension Double {
}
- extension 키워드를 사용해서 기존의 Double 클래스에 추가하려는 인스턴스화(instanced) 메서드를 생성할 수 있다.
- 인스턴스화 메서드: 선언된 프로그램에만 존재하기 때문, 즉 영구적으로 Double 클래스 변경 X
- 스위프트 표준 라이브러리 타입의 기능은 대부분 익스텐션으로 구현되어 있다.
2-1. 익스텐션 확장(+프로토콜)
- 기존에 존재하는 타입이 추가적으로 다른 프로토콜을 채택할 수 있도록 확장할 수 있다.
extension 확장할 타입 이름: 프로토콜1, 프로토콜2, 프로토콜3... {
/*프로토콜 요구사항 구현*/
}
//ex
extension String: protocol1, protocol2 {
}
- 클래스를 이미 구현한 후에 수정할 필요가 생겼다
- 클래스 코드를 수정할 수 있지만, extension을 통해서 클래스를 확장시킬 수도 있다.
- 확장구문에서 프로토콜을 구현한 다면 이후로 해당 클래스는 프로토콜을 구현한 것으로 처리
- 기존 클래스를 수정하지 않아도 된다.
class Guest{
var name: String?
init(name: String = "ㄱㅅㄱ"){
self.name = name
}
}
protocol Reservation {
func printReservation()
}
//Guest 클래스의 기능을 extension을 통해서 확장
extension Guest: Reservation {
func printReservation(){
print("\\(self.name) 님이 예약하였습니다.")
}
}
var guest = Guest(name: "ㄱㅅㄱ")
guest.printReservation() //Optional("ㄱㅅㄱ") 님이 예약하였습니다.
- 프로토콜을 정의할 때는 그 프로토콜을 채택한 타입에서 구현해주어야 하는 프로토콜의 요구사항을 구현할 수 없다. 단지 요구사항을 정의만 할 수 있다.
- 프로토콜의 익스텐션에는 프로토콜이 요구하는 기능을 실제로 구현해 줄 수 있다.
- 다만 익스텐션에는 저장 프로퍼티를 구현할 수 없으므로 저장 프로퍼티는 각각의 타입에서 직접 구현
- 프로토콜 초기 구현(protocol default implementations): 프로토콜의 요구사항을 익스텐션을 통해 구현하는 것 → 프로토콜 채택만으로 타입에 기능을 추가해 사용할 수 있다(프로토콜 지향 프로그래밍 Protocol Oriented Programming POP의 핵심 콘셉)
- 프로토콜의 익스텐션에서 구현한 기능을 사용하지 않고 타입의 특성에 따라 조금 변경해서 구현하고 싶다면 재정의하면 된다.
3. 익스텐션 구현
3-1. 연산 프로퍼티 추가
- 연산 프로퍼티(computed property): 값을 저장하지 않는 대신 연산 결과를 반환한다.
- getter, setter 연산 속성의 값을 지정하거나 가져오는 코드
- 읽기 전용 연산 속성: 값 지정은 안되고 가져오기만 가능, getter 코드 블록만 갖는다.
extension Int { var isEven: Bool { //코드 블록의 표현식에서 반환된 값을 속성에 저장 return self % 2 == 0 } var isOdd: Bool { return self % 2 == 1 } }
- 코드 블록: 연산 속성의 값을 계산하는 getter 코드
- self 속성을 호출했던 Int의 값을 참조하며, 계산하기 위한 표현식에서 사용
//숫자를 쓰게 되면 정수타입: Int타입의 인스턴스를 나타내는 리터럴 문법 print(1.isEven) // false print(2.isOdd) // false var number: Int = 3 print(number.isEven) // false print(number.isOdd) // true number = 2 print(number.isEven) // true print(number.isOdd) // false
- 익스텐션으로 Int타입에 추가해 준 연산 프로퍼티는 Int타입의 어떤 인스턴스에도 사용이 가능합니다
3-2. 메서드 추가
extension Int {
func multiply(by n: Int) -> Int {
return self * n
}
}
//Int 타입의 리터럴문법 -> Int 타입의 인스턴스로 취급
print(3.multiply(by: 2)) // 6
print(4.multiply(by: 5)) // 20
number = 3
print(number.multiply(by: 2)) // 6
print(number.multiply(by: 3)) // 9
- 여러 기능을 여러 익스텐션 블록으로 나눠서 구현해도 문제없다.
- 관련된 기능별로 하나의 익스텐션 블록에 묶어주는 것도 좋다.
3-3. 이니셜라이저 추가
extension String {
//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"
print(stringFromInt is Int) //false
print(stringFromInt is String) //true
- 타입의 정의부에 이니셜라이저를 추가하지 않더라도 익스텐션을 통해 이니셜라이저를 추가할 수 있다.
참고하였습니다. 감사합니다.
https://yagom.net/courses/swift-basic/lessons/타입-확장/topic/익스텐션/
https://yagom.net/courses/swift-basic/lessons/프로토콜-지향-프로그래밍-p-o-p/
https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1903?tab=note&mm=null
23.07.10 수정) Swift 쉽게, 더 쉽게
728x90
'Swift 기초 정리' 카테고리의 다른 글
[Swift 코테 기초] 고차함수 (0) | 2022.04.12 |
---|---|
[Swift 기초] 오류처리 (0) | 2022.04.11 |
[Swift 기초] 프로토콜 (0) | 2022.04.05 |
[Swift 기초] assert와 guard (0) | 2022.04.05 |
[Swift 기초] 자동참조계수, 강한참조, 약한참조 (0) | 2022.04.04 |