스위프트에서는 전역 함수나 서브클래싱 할 필요 없이 확장을 사용해 이미 존재하는 타입에 기능을 추가할 수 있다.
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
기존 객체지향 프로그래밍 언어에서는 기능을 추가하고자 할때 서브클래싱 하여 기능을 추가했다.
반면 확장을 사용하면
- 확장은 기능을 추가하게 설계되었으며, 타입의 기능을 변경하는 의미로 설계되지는 않았다.
- 저장 프로퍼티는 추가할 수 없다.
- 연산 프로퍼티 추가는 가능하다.
스위프트 표준 라이브러리 타입 중 Int를 확장하여 팩토리얼 메소드 추가하기
// 팩토리얼 만들기
// 5! == 5*4*3*2*1
// 5! == 120
extension Int {
func factorial() -> Int {
var answer = 1
for x in (1...self).reversed(){
answer *= x
}
return answer
}
}
print(5.factorial()) // 120
프로토콜 확장은 특정 프로토콜을 따르는 모든 타입에 공통적인 기능을 제공하기 위해 사용된다.
extension Collection {
func shuffle() -> [Interator.Element] {
return sorted(){ left, right in
return arc4random() < arc4random()
}
}
}
var originArray = [1,2,3,4,5]
var ranArray = originArray.shuffle() //← 구현안하고 바로 사용함
Collection 프로토콜을 따르는 모든 타입은 shuffle() 함수를 받게 될 것이다.
→ 프로토콜 확장에 정의된 메서드는 요구사항에 포함되지 않는다. 프로토콜을 따르는 타입에서 해당 메서드를 구현하지 않고 바로 사용할 수 있다.
프로토콜 확장에서 정의된 기능을 전달받을 수 있는 타입을 제한하는 제약 을 확장에 추가할 수도 있다.
// Collection 프로토콜 확장에서는 ExpressibleBytArrayLiteral 프로토콜을 따르는 타입만 확장에서 정의한 기능을 전달 받을 수 있다.
extension Collection where Self: ExpressibleBytTrrayLiteral {
// 확장 코드 ...
}
// 컬렉션 안에 있는 요소가 Comparable 프로토콜을 따르도록
extension Collection where Iterator.Element: Comparable {
...
}