728x90
반응형

익스텐션 (extension)

익스텐션은 스위프트의 강력한 기능 중 하나다.
익스텐션은 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있는 기능이다.
기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하거나 볼 수 없다 해도, 타입만 알고 있다면 그 타입의 기능을 확장할 수 있다.

스위프트의 익스텐션이 타입에 추가할 수 있는 기능

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

‼️ 익스텐션은 타입에 새로운 기능을 추가할 수는 있지만, 기존에 존재하는 기능을 재정의할 수는 없다.

클래스의 상속과 익스텐션의 비교

클래스의 상속

클래스 타입에서만 가능하다.
특정 타입을 물려받아 하나의 새로운 타입을 정의하고 추가 기능을 구현하는 수직 확장
상속받은 클래스에서 오버라이딩을 통해 기존 기능을 재정의할 수 있다.

익스텐션

구조체, 클래스, 프로토콜 등에 적용 가능하다.
기존의 타입에 기능을 추가하는 수평 확장
익스텐션은 기존에 있던 기능을 재정의 할 수 없다.

외부 라이브러리나 프레임워크를 가져다 사용하면 원본 소스를 수정하지 못한다.
따라서 외부에서 가져온 라이브러리에서 익스텐션을 통해 원하는 기능을 골라서 사용할 때 익스텐션을 사용한다.
익스텐션을 모든 타입에 적용할 수 있다.
또한 프로토콜과 함께 사용하면 강력한 기능을 제공해준다.

프로토콜 중심 프로그래밍에 대해서 더 공부해봐야겠다.

익스텐션 정의

익스텐션은 extension 키워드를 통해 정의할 수 있고 다음과 같이 사용할 수 있다.

extension 확장할 타입 이름 {
    /*타입에 추가될 새로운 기능 구현*/
}

 

익스텐션은 기존에 존재하는 타입이 추가적으로 다른 프로토콜을 채택할 수 있도록 확장할 수 있다.
이전에 프로토콜과 델리게이트 패턴에 대해서 공부하면서 확장에 대해서도 살짝 공부했었는데
프로토콜, 델리게이트 패턴과 같이 익스텐션 또한 중요한 부분이라고 생각한다.
그래서 추가적으로 다른 프로토콜을 채택하려면 다음과 같이 사용하면 된다.

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

스위프트 라이브러리를 보게되면 익스텐션이 정말 많이 사용된다.
iOS 공부를 하면서 delegate 와 datasource 를 사용할 때에도 익스텐션을 통해 사용했었다.

익스텐션 구현

익스텐션을 구현하기 전에 익스텐션은 모든 타입을 적용할 수 있고 다양한 기능을 추가할 수 있다.

연산 프로퍼티 추가

Int 타입에 두 개의 연산 프로퍼티를 추가해 보았다.
Int 타입의 인스턴스가 홀수인지 짝수인지 알려주는 연산 프로퍼티다.
익스텐션으로 Int 타입에 추가해준 연산 프로퍼티는 Int 타입의 어떤 인스턴스에도 사용이 가능하다.
인스턴스 연산 프로퍼티를 추가할 수도 있으며, static 키워드를 사용하여 타입 연산 프로퍼티도 추가할 수 있다.

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

print(1.isEven)
print(2.isEven)
print(1.isOdd)
print(1.isOdd)

========== 출력 결과 ==========
false
true
true
true

메서드 추가

메서드 익스텐션을 통해 Int 타입에 인스턴스 메서드 multiply(by:) 메서드를 추가해보았다.
여러 기능을 여러 익스텐션 블록으로 나눠서 구현해도 전혀 문제가 없고
관련된 기능별로 하나의 익스텐션 블록에 묶어주는 것도 좋다고 한다.

extension Int {
    func multiply(by n: Int) -> Int {
        return self * n
    }
}

print(3.multiply(by: 2))
print(4.multiply(by: 5))


var number: Int = 3
print(number.multiply(by: 2))
print(number.multiply(by: 3))

========== 출력 결과 ==========
6
20
6
9

이니셜라이저 추가

인스턴스를 초기화(이니셜라이즈)할 때 인스턴스 초기화에 필요한 다양한 데이터를 전달받을 수 있도록
여러 종류의 이니셜라이저를 만들 수 있다.
타입의 정의 부분에 이니셜라이저를 추가하지 않더라도 익스텐션을 통해 이니셜라이저를 추가할 수 있다.
익스텐션으로 클래스 타입에 편의 이니셜라이저는 추가할 수 있지만, 지정 이니셜라이저는 추가할 수 없다.
지정 이니셜라이저와 디이니셜라이저는 반드시 클래스 타입의 구현부에 위치해야 한다.
값 타입은 상관없다..

extension String {
    init(intTypeNumber: Int) {
        self = "\(intTypeNumber)"
    }
    
    init(doubleTypeNumber: Double) {
        self = "\(doubleTypeNumber)"
    }
}

let stringFromInt: String = String(intTypeNumber: 100)
let stringFromDouble: String = String(doubleTypeNumber: 100.0)

 

- 참고 사이트 - 

www.edwith.org/boostcamp_ios/lecture/11319/

 

[LECTURE] 27. 익스텐션 : edwith

:: 익스텐션 :: 1. 익스텐션 익스텐션(Extension) 은 스위프트의 강력한 기능 중 하나입니다. 익스텐션은 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가 ... - 부스트코스

www.edwith.org

 

728x90
반응형
복사했습니다!