정의
- 기존 클래스, 구조체, 열거형, 프로토콜 타입에 새로운 기능을 추가하는 기능입니다.
사용
: 익스텐션 기능을 활용하여 다음과 같은 기능을 추가할 수 있습니다.
- 연산 타입 프로퍼티, 연산 인스턴스 프로퍼티
- 타입 메서드
- 인스턴스 메서드
- 이니셜라이저
- 서브스크립트
- 중첩타입(새로운 중첩 타입 정의와 사용)
- 기존 타입에 특정 프로토콜을 추가
*extension기능을 통해 기존의 존재하는 기능은 추가할 수 없습니다.*
형식
extension [확장할 타입 이름] {
// 추가구현할 기능
}
프로토콜 추가 형식
extension [확장할 타입 이름]: 프로토콜1, 프로토콜2, ... {
// 프로토콜 요구사항
}
연산 프로퍼티 (Computed Properties)
- 다음 예제는 5개의 연산 인스턴스 속성을 Swift에 Double 타입에 추가하는 예제입니다.
- 입력하는 단위의 값에 따라, 호출시키는 단위로 변환시켜 출력시킵니다.
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")
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
실행결과
// prints "One inch is 0.0254 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()
}
- 이니셜라이저를 통해 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을 사용해 특정 중앙 좌표와 크기를 갖는 이니셜라이저를 추가하겠습니다.
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))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
- 완성된 코드
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))
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)
}
}
let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))
print(centerRect)
실행결과
// Rect(origin: main.Point(x: 2.5, y: 2.5), size: main.Size(width: 3.0, height: 3.0))
*익스텐션을 이용해 새로운 이니셜라이저를 정의한다면, 이니셜라이저가 완료되었을 때
각 인스턴스가 완전히 초기화되었는지 확인해야합니다.*
메서드(Methods)
- 익스텐션은 새로운 인스턴스 메서드와 타입 메서드를 기존 타입에 추가할 수 있습니다.
- Int 타입에 인스턴스 메서드를 추가하는 예제입니다.
extension Int {
func repetitions(task: () -> ()) {
for _ in 0..<self {
task()
}
}
}
- repetitions 메서드는 타입 ( ) -> ( ) 이라는 단일 인자를 갖기 때문에, 인자와 반환 값을 가지지 않습니다.
- 익스텐션을 정의한 후, Int 타입에서 repetitions 메서드를 호출해 원하는 만큼의 문구를 출력할 수 있습니다.
3.repetitions{
print("hello")
}
실행결과
// hello
// hello
// hello
서브스크립트(Subscripts)
- 익스텐션을 통해 기존 타입에 새로운 서브스크립트를 추가할 수 있습니다.
- Int 타입에 서브스크립트를 추가하는 예제입니다.
- 서브스크립트는 제시된 숫자 오른쪽에서 [n]소수 자릿수를 반환합니다.
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
746381295[0]
746381295[1]
746381295[2]
746381295[8]
실행결과
// returns 5
// returns 9
// returns 2
// returns 7
중첩 타입(Nested Types)
- 익스텐션은 기존 클래스, 구조체, 열거형에서 새로운 중첩타입을 추가할 수 있습니다.
- Int 타입에 새로운 중첩 열거형 타입을 추가하여,
Kind라는 열거형에 정수 종류를 각각 zero, positive, negative로 나타냅니다.
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
}
}
}
- printIntegerKinds 함수를 통해 각 인스턴스 속성을 입력된 기호로 반환시켜줍니다.
func printIntegerKinds(numbers: [Int]) {
for number in numbers {
switch number.kind {
case .Negative:
print("- ")
case .Zero:
print("0 ")
case .Positive:
print("+ ")
}
}
print("\n")
}
- 실행하여 결과를 출력해보겠습니다.
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
}
}
}
func printIntegerKinds(numbers: [Int]) {
for number in numbers {
switch number.kind {
case .Negative:
print("- ")
case .Zero:
print("0 ")
case .Positive:
print("+ ")
}
}
print("\n")
}
printIntegerKinds(numbers: [3, 19, -27, 0, -6, 0, 7])
실행결과
// +
// +
// -
// 0
// -
// 0
// +
내용출처
https://www.youtube.com/watch?v=VRkCPbN_XPs&list=PLz8NH7YHUj_ZmlgcSETF51Z9GSSU6Uioy&index=27
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
'iOS > Swift 문법 심화 학습' 카테고리의 다른 글
클로저 (0) | 2022.02.01 |
---|---|
값 타입과 참조 타입 (0) | 2022.01.31 |
guard (0) | 2022.01.28 |
assert (0) | 2022.01.28 |
Initializer (0) | 2022.01.27 |
댓글