본문 바로가기

Swift Language

Swift Language - 19 - 익스텐션 (Extensions)

익스텐션을 이용해 클래스, 구조체, 열거형 혹은 프로토콜 타입에 기능을 추가할 수 있습니다. Swift에서 익스텐션을 이용해 다음을 할 수 있습니다.

  1. 계산된 인스턴스 프로퍼티와 계산된 타입 프로퍼티의 추가
  2. 인스턴스 메소드와 타입 메소드의 추가
  3. 새로운 이니셜라이저 제공
  4. 서브스크립트 정의
  5. 중첩 타입의 선언과 사용
  6. 특정 프로토콜을 따르는 타입 만들기

 

익스텐션 문법 (Extension Syntax)

// 익스텐션은 extension 키워드를 사용해 선언합니다.
extension SomeType {
    // new functionality to add to SomeType goes here
}


// 하나의 익스텐션에서 현재 존재하는 타입에 한개 이상의 프로토콜을 따르도록 확장할 수 있습니다.
extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}

 

계산된 프로퍼티 (Computed Properties)

// 익스텐션을 이용해 존재하는 타입에 계산된 인스턴스 프로퍼티와 타입 프로퍼티를 추가할 수 있습니다. 
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"

 

이니셜라이저 (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()
}

// 기본적으로 제공되는 이니셜라이저를 사용해 초기화를 한 예제입니다.
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
   size: Size(width: 5.0, height: 5.0))
   
   
// 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)
    }
}


// Rect에서 확장한 이니셜라이저를 사용한 코드는 다음과 같이 사용할 수 있습니다.
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)

 

메소드 (Methods)

/* 익스텐션을 이용해 존재하는 타입에 인스턴스 메소드나 타입 메소드를 추가할 수 있습니다. 
다음 예제는 Int 타입에 repetitions라는 인스턴스 메소드를 추가한 예제 입니다. */
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}

3.repetitions {
    print("Hello!")
}
// Hello!
// Hello!
// Hello!

 

변경 가능한 인스턴스 메소드 (Mutating Instance Methods)

/* 익스텐션에서 추가된 인스턴스 메소드는 인스턴스 자신(self)을 변경할 수 있습니다. 
구조체와 열거형 메소드 중 자기 자신(self)를 변경하는 인스턴스 메소드는 
원본 구현의 mutating 메소드와 같이 반드시 mutating으로 선언돼야 합니다. */
extension Int {
    mutating func square() {
        self = self * self
    }
}
var someInt = 3
someInt.square()
// someInt is now 9

 

서브스크립트 (Subscripts)

/* 익스텐션을 이용해 존재하는 타입에 새로운 서브스크립트를 추가할 수 있습니다. 
다음 예제는 Swift의 built-in 타입에 integer 서브스크립트를 추가한 예제입니다. 
서브스크립트 [n]은 숫자의 오른쪽에서부터 n번째 위치하는 정수를 반환합니다. */
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
        // 10 * n번째 수로 현재 수를 나눈 것의 나머지
      // 1인 경우 746381295 % 10 -> 5가 나머지
      // 2인 경우 746381295 % 10 -> 9가 나머지
    }
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7


// 만약 Int값에서 요청한 값이 처리할 수 있는 자릿 수를 넘어가면 서브스크립트 구현에서 0을 반환합니다.
746381295[9]
// 9로 처리할 수 있는 자릿 수를 넘어가면 0을 반환
0746381295[9]

 

중첩 타입 (Nested Types)

// 익스텐션을 이용해 존재하는 클래스, 구조체, 열거형에 중첩 타입을 추가할 수 있습니다.
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
        }
    }
}


// 위 예제는 Int에 중첩형 enum을 추가한 예제입니다. Kind라고 불리는 열거형은 Int를 음수, 0, 양수로 표현합니다.



// 아래 예제는 새로운 계산된 프로퍼티 kind를 이용해 특정 수가 음수, 0, 양수 중 어떤 것인지를 나타내는 예제입니다.
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 + "

 

 

출처 https://jusung.gitbook.io/the-swift-language-guide/language-guide/20-extensions