티스토리 뷰
[시작]
- 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있음
- 타입만 안다면 해당 타입의 기능을 확장할 수 있음
- 익스텐션이 타입에 추가할 수 있는 기능들
: 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
: 타입 메서드 / 인스턴스 메서드
: 이니셜라이저
: 서브스크립트
: 중첩 타입
: 특정 프로토콜을 준수할 수 있도록 기능 추가
- 기존에 존재하는 기능을 재정의할 수는 없음
- 외부에서 가져온 타입에 내가 원하는 기능을 추가하고자 할 때 사용
[상속과 익스텐션 비교]
|
상속 |
익스텐션 |
확장 |
수직 확장 (특정 타입을 물려받아 하나의 새로운 타입을 정의하고 추가 기능을 구현) |
수평 확장 (기존의 타입에 기능을 추가) |
사용 |
클래스 |
모든 타입 |
재졍의 |
가능 |
불가능 |
[문법]
- 일반
1 2 3 4 | extension 확장할 타입 이름 { 타입에 추가될 새로운 기능 구현 } | cs |
- 기존에 존재하는 타입이 추가로 다른 프로토콜을 채택할 수 있도록 확장할 수 있음
1 2 3 4 | extension 확장할 타입 이름: 프로토콜... { 타입에 추가될 새로운 기능 구현 } | cs |
[익스텐션으로 추가할 수 있는 기능 - 연산 프로퍼티]
1 2 3 4 5 6 7 8 | extension Double{ var meterToKilometer: Double { return self / 1000 } } let meter = 17592.182 print(meter.meterToKilometer) //17.592182 | cs |
위의 코드는 Double 타입에 익스텐션으로 미터를 킬로미터로 환산해주는 연산 프로퍼티를 확장함.
- 저장 프로퍼티는 추가할 수 없음
- 타입에 정의되어 있는 기존의 프로퍼티에 프로퍼티 감시자를 추가할 수 없음
[익스텐션으로 추가할 수 있는 기능 - 메서드]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | extension Int{ func multiply(by n: Int) -> Int{ return self * n } mutating func multiplySelf(by n: Int) { self = self * n } static func isIntTypeInstance(_ instance: Any) -> Bool{ return instance is Int } } let a = 4 a.multiply(by: 5) //20 Int.isIntTypeInstance(a) //true | cs |
위의 코드는 Int 타입에 익스텐션으로 여러 메서드를 추가함.
- 여러 기능을 여러 익스텐션 블록으로 나누어서 구현하면 코드를 좀더 보기 좋게 짤 수 있겠다.
[익스텐션으로 추가할 수 있는 기능 - 이니셜라이저]
- 클래스 타입에는 익스텐션으로 지정 생성자는 추가할 수 없고, 편의 생성자만 추가할 수 있음
- 지정 생성자와 소멸자는 반드시 클래스 타입의 구현부에 위치해야 함
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | extension String{ init(intTypeNumber: Int) { self = "\(intTypeNumber)" } init(doubleTypeNumber: Double) { self = "\(doubleTypeNumber)" } } let number = 13 let string = String(intTypeNumber: number) //13 (String 타입) class Person{ var name: String init(name: String) { self.name = name } } extension Person{ convenience init() { self.init(name: "Unknown") } } let person = Person() person.name //Unknown | cs |
- 값 타입에 익스텐션으로 생성자를 추가했을 때,
: 모든 저장 프로퍼티에 기본값이 있고,
: 타입에 기본 생성자와 멤버와이즈 생성자 외에 추가 사용자정의 생성자가 없다면,
: 익스텐션으로 사용자정의 생성자를 추가한 이후에도 해당 타입의 기본 생성자와 멤버와이즈 생성자를 호출할 수 있음
(타입 구현 시 생성자를 사용자정의하면 기존에 자동으로 생성되었던 생성자들을 사용할 수 없게 됨)
[익스텐션으로 추가할 수 있는 기능 - 서브스크립트]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | extension String{ subscript(appedValue: String) -> String{ return self + appedValue } subscript(repeatCount: UInt) -> String{ var str: String = "" for _ in 0..<repeatCount{ str += self } return str } } print("abc"["def"]) //abcdef print("abc"[10]) //abcabcabcabcabcabcabcabcabcabc | cs |
[익스텐션으로 추가할 수 있는 기능 - 중첩 데이터 타입]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | extension Int{ enum Kind{ case negative, zero, positive } var kind: Kind{ switch(self){ case 0: return .zero case let x where x > 0: return .positive default: return .negative } } } let number = 42 print(number.kind) //positive | cs |
위 코드는 Int 타입에 열거형 타입과 그것의 연산 프로퍼티를 익스텐션으로 추가함