μλ νμΈμ, κ°μμ λλ€. μ€λμ Extensionμ λν΄μ 곡λΆν΄λ³Έ λ΄μ©μ μ 리νμ΄μ. κ·ΈλΌ μμ!
Swift Document chap.21 Extension λ°λ‘κ°κΈ°
Extensions — The Swift Programming Language (Swift 5.6)
Extensions Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you don’t have access to the original source code (known as retroactive modeling). Extensions
docs.swift.org
Extensions (νμ₯, μ΅μ€ν μ )
Extension(μ΅μ€ν μ , νμ₯)μ κΈ°μ‘΄μ ν΄λμ€λ, ꡬ쑰체, μ΄κ±°ν λλ νλ‘ν μ½ νμ μ μλ‘μ΄ κΈ°λ₯μ μΆκ°νλ κΈ°λ₯μ΄λ€. μ΄λ μ€μ λ‘ ν΄λΉ νμ λ€μ΄ μ μλ μ½λμ μ κ·Όν μ μμ λμλ μ¬μ© κ°λ₯νλ€.
Swiftμ μ΅μ€ν μ μ λ€μκ³Ό κ°μ κΈ°λ₯μ μ 곡νλ€.
- μΈμ€ν΄μ€μ κ³μ° νλ‘νΌν°μ κ³μ° νμ νλ‘νΌν° μΆκ°
- μΈμ€ν΄μ€ λ©μλμ νμ λ©μλ μ μ
- μλΈ μ€ν¬λ¦½νΈ μ μ
- μλ‘μ΄ μ€μ²© νμ μ μ
- κΈ°μ‘΄ μ νμ΄ νΉμ νλ‘ν μ½μ μ€μνλλ‘ λ§λ€μ΄ μ£ΌκΈ°
Swiftμμλ νλ‘ν μ½μ νμ₯νμ¬ μꡬμ¬νμ ꡬνμ μ 곡νκ±°λ νλ‘ν μ½μ μΆκ° κΈ°λ₯μ μΆκ°ν μλ μλ€. νμ₯μΌλ‘ νμ μ μλ‘μ΄ κΈ°λ₯μ μΆκ°ν μλ μμ§λ§ κΈ°μ‘΄μ κΈ°λ₯μ μ€λ²λΌμ΄λ ν μλ μλ€.
Extension Syntax
μ΅μ€ν μ μ extension ν€μλλ‘ μ μΈνλ€.
extension SomeType {
// SomeType μ μΆκ°ν μλ‘μ΄ κΈ°λ₯μ μ¬κΈ°μ λ‘λλ€.
}
μ΅μ€ν μ μ κΈ°μ‘΄ νμ μ νμ₯νμ¬ νλ μ΄μμ νλ‘ν μ½μ μ±ννκ² ν μ μλ€. μ΄λ κ² νλ‘ν μ½μ μ±ννκΈ° μν΄μλ ν΄λμ€, ꡬ쑰체μμ μ±ννλ λ°©γ νκ³Ό λμΌν λ°©μμΌλ‘ νλ‘ν μ½ μ΄λ¦μ μμ±νλ©΄ λλ€.
extension SomeType: SomeProtocol, AnotherProtocol {
// νλ‘ν μ½μ νμ 쑰건 ꡬνμ μ¬κΈ°μ λ‘λλ€.
}
μ΄λ κ² νλ‘ν μ½μ μ±ννλ μμΈν λ°©λ²μ chap.22 νλ‘ν μ½ μμ λ°°μ°λλ‘ νμ.
μ΅μ€ν μ μ μ‘΄μ¬νλ generic νμ μλ μ μ©ν μ μλ€. Genericμ μ΅μ€ν μ μ μ μ©νλ λ°©λ²μ chap.23 Generic μμ μ΄ν΄λ³΄μ.
λ§μ½ μ΅μ€ν μ μ μ¬μ©νμ¬ κΈ°μ‘΄ νμ μ μλ‘μ΄ κΈ°λ₯μ μΆκ°νλ©΄, μΆκ°νκΈ° μ μ μμ±λ μΈμ€ν΄μ€λ€λ μλ‘μ΄ κΈ°λ₯μ μ¬μ©ν μ μλ€.
1. ExtensionμΌλ‘ κ³μ° νλ‘νΌν° (Computed Properties) μΆκ° νκΈ°
μ΅μ€ν μ μ κΈ°μ‘΄ νμ μ κ³μ° νλ‘νΌν°, κ³μ° νμ νλ‘νΌν°λ₯Ό μΆκ°ν μ μλ€.
λ€μ μμ λ 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")
// "One inch is 0.0254 meters" λ₯Ό μΈμν¨
let threeFeet = 3.ft
print("Three feet is \\(threeFeet) meters")
// "Three feet is 0.914399970739201 meters" λ₯Ό μΈμν¨
βΆοΈ μ½λμ€λͺ
μ΄ κ³μ° νλ‘νΌν°λ€μ Double κ°μ΄ νΉμ κΈΈμ΄ λ¨μλ‘ κ³ λ €λμ΄μΌ ν¨μ νννλ€. κ³μ° νλ‘νΌν°λ‘ ꡬνλκΈ΄ νμ§λ§, λΆλμμμ κΈμ κ°μ μ¨μ 거리 λ³νμ νλ λ°©λ²μΌλ‘ κ·Έ κΈμ κ°μ μ ꡬ문μΌλ‘ μ΄ νλ‘νΌν°λ€μ μ΄λ¦μ λ§λΆμΌ μ μλ€. (ex. .mm, .ft ...)
μ΄ μμ μμ 1.0 μ΄λΌλ Double κ°μ 1λ―Έν°λ₯Ό λνλ΄λ κ²μΌλ‘ κ³ λ €νλ€. κ·Έλμ κ³μ° νλ‘νΌν° mμ΄ self λ₯Ό λ°ννλ κ²μ΄λ€. 1.m μ΄λΌλ ννμμ 1.0μ΄λΌλ Double κ°μ κ³μ°νλ κ²μ΄λ€.
λ€λ₯Έ λ¨μλ₯Ό λ―Έν° μΈ‘μ κ°μΌλ‘ νννλ €λ©΄ μ΄λ ν λ³νμ΄ νμνλ€. 1km λ 1000m μ΄λ―λ‘, km κ³μ° μμ±μ 1_000.0μ κ³±νμ¬ λ―Έν°λ‘ ννν μλ₯Ό λ°ννλ€. μ΄μ λΉμ·νκ² 1 λ―Έν°λ 3.28084νΌνΈ μ΄λ―λ‘, ft κ³μ° μμ±μ μ€μ Double κ° 3.28084λ‘ λλμ΄μ νΌνΈλ₯Ό λ―Έν°λ‘ λ°ννλ€. μ΄ μμ±λ€μ μ½κΈ° μ μ©μ΄λ―λ‘, κ°κ²°ν¨μ μν΄ get ν€μλ μμ΄ νννλ€.
let aMarathon = 42.km + 195.m
print("A marathon is \\(aMarathon) meters long")
// "A marathon is 42195.0 meters long" μ μΈμν¨
μ μ½λμ²λΌ, μ΄λ€μ λ°νκ°μ Double νμ μ΄λ©°, Double νμ μ λ°μλ€μ΄λ κ³³λ§λ€ μμ μμμ μ¬μ©ν μ μλ€.
λ¨, μ΅μ€ν μ μ΄ κΈ°μ‘΄ μμ±μ μλ‘μ΄ κ³μ° μμ±μ μΆκ°ν μλ μμ§λ§, μ μ₯ νλ‘νΌν°λ νλ‘νΌν° μ΅μ λ²λ₯Ό μΆκ°ν μλ μλ€.
2. ExtensionμΌλ‘ μλ‘μ΄ μμ±μ (Initializers) μΆκ°νκΈ°
μ΅μ€ν μ μ κΈ°μ‘΄ νμ μ μλ‘μ΄ μμ±μλ₯Ό μΆκ°ν μ μλ€. μ΄λ₯Ό ν΅ν΄ νμ μ νμ₯νμ¬ μ»€μ€ν νμ μ μμ±μμ 맀κ°λ³μλ‘ λ°κ±°λ, μλ μλ μμ±μλ₯Ό μ 곡ν μ μλ€. μ΅μ€ν μ μ ν΄λμ€μ μλ‘μ΄ convenience μμ±μλ₯Ό μΆκ°ν μλ μμ§λ§, designated μμ±μλ μλ©Έμλ μΆκ°ν μ μλ€. μ΄λ¬ν λΆλΆμ νμ μ€μ ν΄λμ€ κ΅¬νλΆμμ μ μλμ΄μΌ νλ€.
μμ μ λͺ¨λ μ μ₯ νλ‘νΌν°μ defaultκ°μ μ 곡νλ©΄μ, μ΄λ€ μμ±μλ μ 곡νμ§ μμ κ° νμ μ μ΅μ€ν μ μΌλ‘ μμ±μλ₯Ό μΆκ°νλ©΄, μ΅μ€ν μ μ μμ±μ μμμ κ·Έ κ° νμ μ default μμ±μμ memberwise μμ±μλ₯Ό νΈμΆ ν μ μλ€.
λ€λ₯Έ λͺ¨λμμ μ μΈν ꡬ쑰체μ μ΅μ€ν μ μΌλ‘ μμ±μλ₯Ό μΆκ°νλ©΄, μλ‘μ΄ μμ±μκ° μ μ λͺ¨λμ μλ μμ±μλ₯Ό νΈμΆνκΈ° μ κΉμ§λ selfμ μ κ·Όν μ μλ€.
μλ μμ λ μ¬κ°νμ λνλ΄λ Rect ꡬ쑰체μ΄λ€. Sizeμ PointλΌλ λ κ°μ ꡬ쑰체λ μ μνλ€. λ ꡬ쑰체λ λ λ€ λͺ¨λ μμ±μ 0.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()
}
Rect ꡬ쑰체λ μμ μ λͺ¨λ μμ±μ κΈ°λ³Έ κ°μ μ 곡νκΈ° λλ¬Έμ, μλμΌλ‘ default μμ±μμ memberwise μμ±μλ₯Ό λ°λλ€. μ΄ μμ±μλ€μ μ¬μ©νμ¬ μλ‘μ΄ 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)
}
}
let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))
// centerRect μ μμ μ (2.5, 2.5) μ΄κ³ , ν¬κΈ°λ (3.0, 3.0) μ
μ΄ μλ‘μ΄ μμ±μμ μμμ center λ° size κ°μ κΈ°μ΄νμ¬ μ μ ν μμ μ κ³μ°νλ κ²μ΄λ€. κ·Έλ° λ€μ μμ±μλ memberwise μμ±μλ₯Ό μλμΌλ‘ νΈμΆν΄μ μλ‘μ΄ κ°μ μ μ ν νλ‘νΌν°μ μ μ₯νλ€.(init) μ΄λ κ² μ΅μ€ν μ μΌλ‘ μΆκ°ν μμ±μλ μ΄κΈ°νκ° μλ£λλ©΄ μΈμ€ν΄μ€κ° μμ ν μ΄κΈ°ν λλλ‘ ν΄μΌνλ€.
3. ExtensionμΌλ‘ μΈμ€ν΄μ€ λ©μλ (Methods), νμ λ©μλ μΆκ°νκΈ°
μ΅μ€ν μ μ κΈ°μ‘΄ νμ μ μλ‘μ΄ μΈμ€ν΄μ€ λ©μλ λ° νμ λ©μλλ₯Ό μΆκ°ν μ μλ€. λ€μ μμ λ Int νμ μ repetitions μ΄λΌλ μ μΈμ€ν΄μ€ λ©μλλ₯Ό μΆκ°ν μ½λμ΄λ€.
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
}
repetition(task: )λ©μλλ () -> Void νμ μ λ¨μΌ μΈμλ₯Ό μ·¨νλλ°, μ΄λ 맀κ°λ³μλ μκ³ κ°λ λ°ννμ§ μλ ν¨μλ₯Ό μ§μνλ€.
μ΄ μ΅μ€ν μ μ μ νμλ μ΄λ€ μ μμμλ repetition(task: ) λ©μλλ₯Ό νΈμΆνμ¬ κ·Έ νμ λ§νΌ μ무λ₯Ό μνν μ μλ€.
3.repetitions {
print("Hello!")
}
// Hello!
// Hello!
// Hello!
3.1 Mutating Instance Methods (λ³κ²½ μΈμ€ν΄μ€ λ©μλ)
μ΅μ€ν μ μΌλ‘ μΆκ°ν μΈμ€ν΄μ€ λ©μλλ κ·Έ μ체λ₯Ό μμ λλ λ³κ²½ (Mutate) ν μ μλ€. ꡬ쑰체μ μ΄κ±°νμ λ©μλλ κ° νμ μ΄λ―λ‘ μ체μ μΌλ‘ μμ νκΈ° μν΄μλ mutating ν€μλλ₯Ό ν¨κ» μ¬μ©ν΄μ λ©μλλ₯Ό μΆκ°ν΄μΌ νλ€.
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt λ μ΄μ 9 μ
4. ExtensionμΌλ‘ μλ‘μ΄ μλΈμ€ν¬λ¦½νΈ (Subscripts) μΆκ°νκΈ°
μ΅μ€ν μ μ κΈ°μ‘΄ νμ μ μλ‘μ΄ μλΈμ€ν¬λ¦½νΈλ₯Ό μΆκ°ν μ μλ€.
λ€μ μμ λ μ€μννΈ λ΄μ₯ Int νμ μ μ μ μλΈμ€ν¬λ¦½νΈλ₯Ό μΆκ°νλ μ½λμ΄λ€. [n] μ΄λΌλ μ΄ μλΈμ€ν¬λ¦½νΈλ μμΉ κ° μ€λ₯Έ μͺ½μμ n λ²μ§Έ μ리μ 10μ§ μ«μλ₯Ό λ°ννλ€.
- 123456789[0] μ 9 λ₯Ό λ°ν
- 123456789[1] μ 8μ λ°ν
extension Int {
subscript**(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// 5 λ₯Ό λ°νν¨
746381295[1]
// 9 λ₯Ό λ°νν¨
746381295[2]
// 2 λ₯Ό λ°νν¨
746381295[8]
// 7 μ λ°νν¨
Int κ°μ μμ²ν n μ΄ λ²μλ₯Ό λμ΄κ°λ©΄, 0μ λ°ννλ€.
746381295[9]
// λ§μΉ μ΄λ κ² μμ²ν κ²μ²λΌ, 0 μ λ°νν¨:
0746381295[9]
5. ExtensionμΌλ‘ κΈ°μ‘΄ ν΄λμ€, ꡬ쑰체, μ΄κ±°νμ μ€μ²© νμ (Nested Type) μΆκ°νκΈ°
μ΅μ€ν μ μ κΈ°μ‘΄μ ν΄λμ€, ꡬ쑰체, μ΄κ±°νμ μλ‘μ΄ μ€μ²© νμ μ μΆκ°ν μ μλ€.
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μ μλ‘μ΄ μ€μ²© μ΄κ±°νμ μΆκ°νλ€. KindλΌλ μ΄ μ΄κ±°νμ ν νΉλ³ν μ μκ° λνλ΄λ μμΉ κ°μ μ’ λ₯λ₯Ό λνλΈλ€. μμΉ κ°μ΄ μμμΈμ§, 0, μμμΈμ§λ₯Ό ννν΄μ€λ€.
λλ²μ§Έ λ¨λ½μμ, κ·Έ μ μμ λν μ μ ν Kind μ΄κ±°νμ λ°ννλ, kind(μλ¬Έμ) λΌλ μλ‘μ΄ μΈμ€ν΄μ€ μμ±λ Intμ μΆκ°ν΄μ£Όμλ€.
func printIntegerKinds(_ number: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("- ", terminator: "")
case .zero:
print("0 ", terminator: "")
case .positive:
print("+ ", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// "+ + - 0 - 0 + " λ₯Ό μΈμν¨
μμμ μΆκ°ν Kind μ΄κ±°νμ μ¬μ©νμ¬ printIntegerKinds(_: ) λ©μλλ₯Ό μ μνλ€. μ΄ ν¨μλ μ΄λ ν μ μμ λνμ¬ μμλ©΄ -, μμλ©΄ +, 0μ΄λ©΄ 0μ μΆλ ₯νλ€.