Search

[Swift 공식 문서] 21. Extensions

안녕하세요 iOS 개발자 워너비 루크입니다
오늘은 Swift 공식 문서의 Extensions 부분에 대해서 공부해보려고 합니다.

Extensions

Extension(익스텐션)은 기존의 클래스, 구조체, 열거형, 프로토콜들에 새로운 기능을 추가하는 데 사용됩니다.
원본 소스코드에 대한 접근이 허용되지 않은 타입에 또한 기능의 확장이 가능해집니다.
익스텐션이 제공하는 기능은 아래와 같습니다.
 계산 프로퍼티, 계산 타입 프로퍼티 추가
 인스턴스, 타입 메서드 추가
새로운 initializer 추가
subscript 정의
새로운 중첩 타입 정의
 이미 존재하는 타입이 프로토콜을 준수하도록 만들기
프로토콜의 요구조건 또한 확장이 가능합니다.
extension 은 새로운 기능을 추가만 가능할 뿐, override 하지 않습니다.

Extension Syntax

extension SomeType { // new functionality to add to SomeType goes here }
Swift
복사
익스텐션을 사용하면 기존의 클래스에 추가적인 프로토콜을 채택시킬 수 있습니다. 프로토콜의 추가는 기존 클래스에 프로토콜을 채택하는 방법과 동일합니다.
extension SomeType: SomeProtocol, AnotherProtocol { // implementation of protocol requirements goes here }
Swift
복사
추가적으로 프로토콜을 준수하는 방법은 Adding Protocol Conformance with an Extension. 에서 확인할 수 있습니다,
generic 타입 또한 익스텐션 적용이 가능합니다. 제네릭에 익스텐션을 적용하는 방법은 Extending a Generic Type 문서를 참고하세요

Computed Properties

익스텐션을 활용하면 기존의 타입에 컴퓨티드 프로퍼티와 컴퓨티드 타입 프로퍼티를 추가로 정의할 수 있습니다.
아래는 Swift 의 내장 타입인 Double 에 계산 프로퍼티를 추가한 예제입니다
extension Double { var km: Double { return self * 1_000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1_000.0 } var ft: Double { return self / 3.28084 } } let oneInch = 25.4.mm print("One inch is \(oneInch) meters") // Prints "One inch is 0.0254 meters" let threeFeet = 3.ft print("Three feet is \(threeFeet) meters") // Prints "Three feet is 0.914399970739201 meters"
Swift
복사
위에서 추가된 계산 프로퍼티들은 여러가지 길이 단위를 표현합니다. 계산 프로퍼티로 구현되었으나, 이렇게 추가된 프로퍼티들은 리터럴 값에 사용이 가능합니다.
이러한 프로퍼티들은 read-only 인 계산 프로퍼티임을 명심합시다.
따라서 get 키워드의 생략이 가능합니다
리턴값이 Double 이므로 리턴 값을 수학적인 계산에 사용이 가능합니다.
let aMarathon = 42.km + 195.m print("A marathon is \(aMarathon) meters long") // Prints "A marathon is 42195.0 meters long"
Swift
복사
익스텐션으로는 다음 기능들을 추가할 수 없습니다.
stored property
property observer

Initializers

기존 타입에 새 생성자를 추가할 수 있습니다.
커스텀 타입을 활용한 새로운 생성자 추가가 가능합니다!
새 convenience 생성자를 class 에 추가할 수 있습니다.
새 desiganated 생성자 또는 deinitializer 는 추가할 수 없습니다.
designated 생성자 와 deinitializer 는 반드시 클래스 원본에 정의 되어야합니다.
만약 value 타입에 새 생성자를 추가하는 경우, 새 생성자에서 모든 스토어드 프로퍼티에 초기값을 반드시 주어야합니다.
새로이 추가한 생성자 내부에서 기존 생성자를 호출할 수 있습니다.
단 커스텀 생성자는 ㄴ호출이 불가능합니다.
struct Size { var width = 0.0, height = 0.0 } struct Point { var x = 0.0, y = 0.0 } struct Rect { var origin = Point() var size = Size() }
Swift
복사
위 예시에서 Rect 구조체는 모든 프로퍼티에 대한 초기값을 제공했으므로,
자동으로 기본 생성자를 사용할 수 있습니다.
let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
Swift
복사
Rect 구조체에 추가적인 생성자를 추가할 수 있습니다.
extension Rect { init(center: Point, size: Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origin: Point(x: originX, y: originY), size: size) } }
Swift
복사
위 예시에서 기본 생성자를 호출하는 모습을 확인할 수 있습니다.

Methods

익스텐션들은 새 인스턴스 메서드를 추가할 수 있습니다.
extension Int { func repetitions(task: () -> Void) { for _ in 0..<self { task() } } } 3.repetitions { print("Hello!") } // Hello! // Hello! // Hello!
Swift
복사
위는 Int 타입에 새로운 메서드를 추가한 예시입니다.

Mutating Instance Methods

인스턴스 자기 자신을 변경하는 메서드를 extension 에 선언할 수 있습니다.
self 를 변경하는 구조체와 열거형 메서드들은 mutating 이라는 키워드를 앞에 작성해주어야 합니다.
extension Int { mutating func square() { self = self * self } } var someInt = 3 someInt.square() // someInt is now 9
Swift
복사

Subscripts

extension을 사용해 존재하는 타입에 새 subscript 를 추가할 수 있습니다.
extension Int { subscript(digitIndex: Int) -> Int { var decimalBase = 1 for _ in 0..<digitIndex { decimalBase *= 10 } return (self / decimalBase) % 10 } } 746381295[0] // returns 5 746381295[1] // returns 9 746381295[2] // returns 2 746381295[8] // returns 7
Swift
복사
만약 Int 값이 인덱스에 해당하는 자리수 를 가지지 못한다면, 0 을 리턴하게 된다.

Nested Types

extension 을 활용하면 이미 존재하는 클래스, 구조체, 열거형에 중첩 타입을 추가할 수 있습니다.
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 } } }
Swift
복사
위 예제에서는 Int 형에 새 중첩 열거형을 추가했다.
이 열거형은 Kind 로 정수형의 종류를 표현한다. ( 음수, 0 , 양수 )
이 예시는 또한 kind 라는 새 계산 인스턴스 프로퍼티를 추가한다.
이렇게 추가된 열거형은 정수의 적절한 Kind 열거형 case를 리턴한다.
이렇게 정의된 case 는 switch 문에 사용이 가능하다.
func printIntegerKinds(_ numbers: [Int]) { for number in numbers { switch number.kind { case .negative: print("- ", terminator: "") case .zero: print("0 ", terminator: "") case .positive: print("+ ", terminator: "") } } print("") } printIntegerKinds([3, 19, -27, 0, -6, 0, 7]) // Prints "+ + - 0 - 0 + "
Swift
복사