Swift

[Swift] Extension(익스텐션)이란?

Hatchling.dev 2023. 6. 15. 20:52

(편의상 편한 말투로 작성하는 점 이해 부탁드립니다.😅)

(부정확한 정보가 있을 수 있습니다. 지적 환영🤩)

 

오늘은 Extension(익스텐션)은 무엇인가!에 대해 알아보도록 하겠습니다.

직역하자면 확장, 연장선 정도로 해석할 수 있겠네요. 실제로 익스텐션은 클래스, 구조체, 열거형, 프로토콜의 기능을 확장하는 기능을 담당합니다. 익스텐션으로 추가할 수 있는 기능들은 다음과 같고, 자세한 내용은 예제 코드를 통해 더 설명드리겠습니다!

 

Extension(익스텐션)에 추가할 수 있는 기능

  • 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
  • 타입 메서드 / 인스턴스 메서드
  • initializer(이니셜라이저)
  • Subscript(서브스크립트)
  • 중첩타입
  • 특정 프로토콜을 준수할 수 있도록 기능 추가

 

예시

1. 연산 프로퍼티 추가

먼저 익스텐션을 통해 새로운 프로퍼티를 생성하는 방법입니다. 익스텐션에서는 연산프로퍼티만 추가할 수 있습니다. 아래 예제는 Int 타입으로 들어온 값이 짝수인지 홀수인지를 저장하는 프로퍼티를 추가하는 예제입니다.

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }
	
    var isOdd: Bool {
        return self % 2 == 1
    }
}

var number = 10
print(number.isEven)    // true
print(number.isOdd)    // false

2. 메서드 추가

이번에는 새로운 메서드를 추가하는 방법입니다. Int 타입의 값을 Double 타입으로 변경하여 출력하는 메서드를 추가해보았습니다!

extension Int {
    func convertDouble() {
        print("\(self)의 Double형은 \(Double(self))입니다.")
    }
}

var number = 10
number.convertDouble()    // 10의 Double형은 10.0입니다.

3. 이니셜라이저

클래스에서는 Convenience init만 추가할 수 있습니다. 구조체에서는 Memberwise init(구조체에서 이니셜라이저를 구현하지 않았을 때 자동으로 만들어지는 이니셜라이저)가 있기 때문에 구조체에서 이니셜라이저를 정의하는 것과 구조체의 익스텐션에서 이니셜라이저를 정의하는 것에는 차이가 있습니다! 아래 코드처럼 구조체 내에 이니셜라이저를 정의하면 해당 이니셜라이저 하나만 나오게 되고 익스텐션을 활용하여 이니셜라이저를 추가하면 자동으로 만들어주는 Memberwise 이니셜라이저와 따로 정의한 이니셜라이저 모두 사용할 수 있게 됩니다.

4. Subscript(서브스크립트)

서브스크립트가 뭔지 모르시는 분들은 접은글을 확인해주세요!

익스텐션에는 아래처럼 서브스크립트를 정의할 수 있습니다. Swift에서는 문자열에 인덱스로 접근하기 번거롭지만 이처럼 인덱스 접근 서브스크립트를 정의해 사용하면 편리하겠네요! (시간복잡도는 나쁘겠지만.....ㅠ)

더보기

Subscript란?

컬렉션, 리스트, 시퀀스 등의 member element에 간단하게 접근할 수 있는 문법으로 클래스, 구조체, 열거형에서 정의하여 사용할 수 있습니다. 예를 들면 특정 메서드 없이 값을 가져오거나 할당할 수 있습니다.

하나의 타입에 여러 subscripts를 정의할 수 있고 overload도 가능하고 필요에 따라 복수 인자 값을 사용할 수 있습니다.

extension String {
    subscript(index: Int) -> String {
        return self.map { String($0) }[index]
    }
}

print("안녕하세요"[2]) 	// "세"

5. 중첩타입

다음은 중첩타입입니다. 아래 코드처럼 타입에 익스텐션을 추가하여 새로운 타입을 정의해 활용할 수 있습니다.

extension Int {
    enum Number {
        case Even, Odd
    }
	
    var number: Number {
        switch self % 2 {
        case 0:
            return .Even
        default:
            return .Odd
        }
    }
}

var number = 10
print(number.number)    // Even

6. 특정 프로토콜을 준수할 수 있도록 기능 추가

아래처럼 익스텐션을 통해 프로토콜을 추가할 수도 있습니다. 예제라서 간단하게 표현했지만 사실 많이 봤던 케이스일수도 있습니다 ㅎㅎ 실제 개발할 때 테이블뷰를 사용해야 할 때 익스텐션을 통해 프로토콜을 준수하도록 코드를 많이 짭니다. (저만 그런가요..?) 이렇게 익스텐션을 통해 프로토콜을 준수하도록 하고 기능을 별도로 구현한다면 가독성 측면에서도 확연히 좋아지는 것 같습니다!

protocol Number {
    func convertString()
}

extension Int: Number {
    func convertString() {
        print(String(self))
    }
}

var number = 10
number.convertString()    // 10

 

오늘은 Extension(익스텐션)에 대해 알아보았습니다!! 익스텐션에 대해 잘 이해하고 사용한다면 가독성 측면에서도 훨씬 좋아지고 기능을 깔끔하게 정의할 수 있을 것 같습니다 ㅎㅎㅎㅎ 다음에는 클로저에 대해 알아보겠습니다!