본문 바로가기
iOS/Swift 문법 심화 학습

extensions

by 황민우 2022. 1. 30.

정의

- 기존 클래스, 구조체, 열거형, 프로토콜 타입에 새로운 기능을 추가하는 기능입니다.


사용

 : 익스텐션 기능을 활용하여 다음과 같은 기능을 추가할 수 있습니다.

- 연산 타입 프로퍼티, 연산 인스턴스 프로퍼티

- 타입 메서드

- 인스턴스 메서드

- 이니셜라이저

- 서브스크립트

- 중첩타입(새로운 중첩 타입 정의와 사용)

- 기존 타입에 특정 프로토콜을 추가

*extension기능을 통해 기존의 존재하는 기능은 추가할 수 없습니다.*

 


형식

extension [확장할 타입 이름] {
	// 추가구현할 기능
}

프로토콜 추가 형식

extension [확장할 타입 이름]: 프로토콜1, 프로토콜2, ... {
	// 프로토콜 요구사항
}

 


 

연산 프로퍼티 (Computed Properties)

- 다음 예제는 5개의 연산 인스턴스 속성을 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")
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")

실행결과
// prints "One inch is 0.0254 meters"
// prints "Three feet is 0.914399970739201 meters"

이니셜라이저(Initializers)

- 익스텐션을 사용하여 기존 타입에 새로운 이니셜라이저를 추가하는 예제입니다.

- 다른 타입을 사용자 타입 이니셜라이저 인자로 받거나, 기본 구현에 포함되지 않는 초기화 옵션을 확장할 수 있습니다.

- 모든 속성에 기본 값을 지정한 구조체 예제입니다.

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()
}

 

- 이니셜라이저를 통해 Rect 인스턴스를 만들었습니다.

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
    size: Size(width: 5.0, height: 5.0))

 

- Rect 구조체에 extension을 사용해 특정 중앙 좌표와 크기를 갖는 이니셜라이저를 추가하겠습니다.

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)
    }
}

 

- 새로운 이니셜라이저는 center 자표와 size 크기를 통해, 기존좌표를 계산하여 적합한 위치로

  멤버 이니셜라이저를 호출하여 초기화합니다.

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
    size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)

 

- 완성된 코드

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()
}

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
    
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)
    }
}

let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))
print(centerRect)

실행결과
// Rect(origin: main.Point(x: 2.5, y: 2.5), size: main.Size(width: 3.0, height: 3.0))

 

*익스텐션을 이용해 새로운 이니셜라이저를 정의한다면, 이니셜라이저가 완료되었을 때

 각 인스턴스가 완전히 초기화되었는지 확인해야합니다.*


메서드(Methods)

- 익스텐션은 새로운 인스턴스 메서드와 타입 메서드를 기존 타입에 추가할 수 있습니다.

- Int 타입에 인스턴스 메서드를 추가하는 예제입니다.

extension Int {
    func repetitions(task: () -> ()) {
        for _ in 0..<self {
            task()
        }
    }
}

 

- repetitions 메서드는 타입 ( ) -> ( ) 이라는 단일 인자를 갖기 때문에, 인자와 반환 값을 가지지 않습니다.

- 익스텐션을 정의한 후, Int 타입에서 repetitions 메서드를 호출해 원하는 만큼의 문구를 출력할 수 있습니다. 

3.repetitions{
    print("hello")
}

실행결과
// hello
// hello
// hello

서브스크립트(Subscripts)

- 익스텐션을 통해 기존 타입에 새로운 서브스크립트를 추가할 수 있습니다.

- Int 타입에 서브스크립트를 추가하는 예제입니다.

- 서브스크립트는 제시된 숫자 오른쪽에서 [n]소수 자릿수를 반환합니다.

extension Int {
    subscript(var digitIndex: Int) -> Int {
        var decimalBase = 1
            while digitIndex > 0 {
                decimalBase *= 10
                --digitIndex
            }
            return (self / decimalBase) % 10
    }
}
746381295[0]
746381295[1]
746381295[2]
746381295[8]


실행결과
// returns 5
// returns 9
// returns 2
// returns 7

중첩 타입(Nested Types)

- 익스텐션은 기존 클래스, 구조체, 열거형에서 새로운 중첩타입을 추가할 수 있습니다.

- Int 타입에 새로운 중첩 열거형 타입을 추가하여,

  Kind라는 열거형에 정수 종류를 각각 zero, positive, negative로 나타냅니다.

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
            }
    }
}

 

- printIntegerKinds 함수를 통해 각 인스턴스 속성을 입력된 기호로 반환시켜줍니다.

func printIntegerKinds(numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .Negative:
            print("- ")
        case .Zero:
            print("0 ")
        case .Positive:
            print("+ ")
        }
    }
    print("\n")
}

 

- 실행하여 결과를 출력해보겠습니다.

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
            }
    }
}
func printIntegerKinds(numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .Negative:
            print("- ")
        case .Zero:
            print("0 ")
        case .Positive:
            print("+ ")
        }
    }
    print("\n")
}
printIntegerKinds(numbers: [3, 19, -27, 0, -6, 0, 7])

실행결과
// +
// +
// -
// 0
// -
// 0
// +

내용출처

https://www.youtube.com/watch?v=VRkCPbN_XPs&list=PLz8NH7YHUj_ZmlgcSETF51Z9GSSU6Uioy&index=27 

https://docs.swift.org/swift-book/LanguageGuide/Extensions.html

'iOS > Swift 문법 심화 학습' 카테고리의 다른 글

클로저  (0) 2022.02.01
값 타입과 참조 타입  (0) 2022.01.31
guard  (0) 2022.01.28
assert  (0) 2022.01.28
Initializer  (0) 2022.01.27

댓글