확장(Extension)은 확장한 클래스와 구조체, 열거형 또는 프로토콜 타입에 새로운 기능을 추가할 수 있다. 스위프트에서 확장은 다음의 기능들을 수행할 수 있다.
- 계산된 인스턴스 프로퍼티와 계산된 타입 프로퍼티 추가
- 인스턴스 메서드와 타입 메서드 정의
- 새로운 초기화 구문 제공
- 서브 스크립트 정의
- 새로운 중첩된 타입의 정의와 사용
- 기존의 타입이 프로토콜을 준수하도록 조치
사실상 확장을 통해서 프로퍼티로부터 메서드까지 다양한 기능들을 거의 제한없이 추가 할 수 있다는 것이다.
extension SomeType {
//새로운 확장 기능과 프로퍼티를 입력
}
//확장은 하나 이상의 프로토콜을 채택해서 기존 타입 확장이 가능하다.
extension SomeType : SomeProtocol, AnotherProtocol {
//프로토콜 확장 기능을 추가
//위처럼 입력 시 해당 확장은 기존의 클래사느 구조체에 대해서 프로토콜 준수를 추가할 수 있다.
}
extension Double {
var km: Double {
return self * 1_000.0
}
//읽기 전용 프로퍼티이므로 별도의 get키워드 없이 다음과 같이 약식으로 표현 가능하다.
var m: Double {
return self
}
}
let aMeter = 25.4.m
print("This is \(aMeter)")
//Double뒤에 .을 찍어서 해당 프로퍼티에 접근을 하고 이를 출력해주었다.
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 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))
//다음과 같이 초기화 구문을 통해서 새로운 지정값을 생성할 수 있다.
extension Int {
func repetition(task : () -> Void) {
for _ in 0..<self {
task()
}
}
}
//repetition(task:)메서드는 파라미터가 없고 반환값이 없는 함수타입의 인자를 가지며,
//확장 정의 후 여러번 작업 수행을 위해 모든 정수로 해당 메서드 호출이 가능하다.
3.repetition {
print("Hello")
}
//Hello를 3회 출력한다.
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
//someInt = 9이다.
extension Int {
subscript(digitIndex : Int) -> Int {
var decimalBase = 1
for _ in 0 ..< digitIndex {
decimalBase *= 10
}
return (self/decimalBase) % 10
}
}
7412412[0]
//2를 리턴한다.
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에 중첩된 새로운 열거형을 추가한다.
//또한 해당 열거형 값에 대해 계산된 프로퍼티를 제공하는 새로운 프로퍼티를 추가 가능하다.
func printIntegerKinds(_ numbers : [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("-")
case .zero:
print("0")
case .positive:
print("+"
}
}
}
//다음과 같이 확장된 중첩된 타입을 활용가능해진다.