μλ νμΈμ. μ€λμ Swift 'μ λλ¦(Generics)'μ λν΄ μμλ³΄κ² μ΅λλ€.
π μ λλ¦μ΄λ? κ·Έλ¦¬κ³ μ νμν κΉμ?
μ λλ¦ μ½λλ νΉμ νμ μ ꡬμ λ°μ§ μκ³ , μ μν μꡬμ¬νμ μΆ©μ‘±νλ λͺ¨λ νμ μ λν΄ λμν μ μλ μ μ°ν μ½λλ₯Ό μμ±ν μ μκ² ν΄μ€λλ€. Swiftμ Array, Dictionaryμ κ°μ νμ€ λΌμ΄λΈλ¬λ¦¬μ λλΆλΆμ μ λλ¦μΌλ‘ ꡬνλμ΄ μμ΅λλ€.
μ λλ¦μ΄ ν΄κ²°νλ λ¬Έμ
μλ μμ λ₯Ό ν΅ν΄ μ λλ¦μ νμμ±μ μ΄ν΄λ³΄κ² μ΅λλ€:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
μ΄ ν¨μλ λ μ μμ κ°μ κ΅ννλ κ°λ¨ν ν¨μμ λλ€. κ·Έλ¬λ λ§μ½ λ¬Έμμ΄μ΄λ μ€μ κ°μ κ΅ννκ³ μΆλ€λ©΄ μ΄λ»κ² ν΄μΌ ν κΉμ?
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
μΈ ν¨μμ λ³Έλ¬Έμ΄ μμ ν λμΌνλ€λ κ²μ μ μ μμ΅λλ€. μ΄λ° μ½λ μ€λ³΅μ μ λλ¦μ ν΅ν΄ ν΄κ²°ν μ μμ΅λλ€.
π μ λλ¦ ν¨μ μμ±νκΈ°
μ λλ¦ ν¨μλ λͺ¨λ νμ μ λν΄ λμν μ μμ΅λλ€. μμ ν¨μλ€μ μ λλ¦μΌλ‘ λ€μ μμ±ν΄ λ΄ μλ€:
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
μ΄ ν¨μλ μ΄λ€ νμ μ΄λ μ¬μ©ν μ μμΌλ©°, λ€μκ³Ό κ°μ΄ νΈμΆν μ μμ΅λλ€:
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someIntλ μ΄μ 107, anotherIntλ μ΄μ 3
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
// someStringμ μ΄μ "world", anotherStringμ μ΄μ "hello"
μ°Έκ³ : μ€μ λ‘ Swift νμ€ λΌμ΄λΈλ¬λ¦¬μλ swap(_:_:) ν¨μκ° μ΄λ―Έ ꡬνλμ΄ μμ΄, μ§μ ꡬνν νμ μμ΄ μ¬μ©ν μ μμ΅λλ€.
νμ νλΌλ―Έν° (Type Parameters)
<T>μμ Tλ νμ νλΌλ―Έν°μ λλ€. ν¨μκ° νΈμΆλ λλ§λ€ μ€μ νμ μΌλ‘ λ체λ©λλ€. νμ νλΌλ―Έν°μ μ΄λ¦μ λκ° λλ¬Έμλ‘ μμνλ©°, T, U, V κ°μ λ¨μΌ λ¬Έμλ Element, Key, Valueμ κ°μ μ€λͺ μ μΈ μ΄λ¦μ μ¬μ©ν©λλ€.
μ¬λ¬ νμ νλΌλ―Έν°λ₯Ό μ¬μ©νκ³ μΆλ€λ©΄ <T, U, V>μ κ°μ΄ μ½€λ§λ‘ ꡬλΆνμ¬ λμ΄ν μ μμ΅λλ€.
π μ λλ¦ νμ μ μνκΈ°
ν¨μλΏλ§ μλλΌ ν΄λμ€, ꡬ쑰체, μ΄κ±°νλ μ λλ¦μΌλ‘ μ μν μ μμ΅λλ€. λ€μμ μ λλ¦ μ€ν(Stack) ꡬνμ μμ λλ€:
struct Stack<Element> {
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
μ΄ μ λλ¦ μ€νμ μ΄λ€ νμ μ μμλ μ μ₯ν μ μμ΅λλ€:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// μ€νμλ μ΄μ 4κ°μ λ¬Έμμ΄μ΄ μμ
let fromTheTop = stackOfStrings.pop()
// fromTheTopμ "cuatro"μ κ°μ
μ λλ¦ νμ νμ₯νκΈ°
μ λλ¦ νμ μ νμ₯ν λλ νμ νλΌλ―Έν° λͺ©λ‘μ λ€μ μμ±νμ§ μμ΅λλ€:
extension Stack {
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
μ΄ νμ₯μ ν΅ν΄ λͺ¨λ Stack μΈμ€ν΄μ€μ topItem μμ±μ΄ μΆκ°λ©λλ€:
if let topItem = stackOfStrings.topItem {
print("μ€νμ μ΅μμ νλͺ©μ \(topItem)μ
λλ€.")
}
// "μ€νμ μ΅μμ νλͺ©μ tresμ
λλ€." μΆλ ₯
π νμ μ μ½ (Type Constraints)
λλ‘λ μ λλ¦ ν¨μλ νμ μ΄ νΉμ νλ‘ν μ½μ μ€μνκ±°λ νΉμ ν΄λμ€λ₯Ό μμνλ νμ μλ§ μλνλλ‘ μ νν΄μΌ ν νμκ° μμ΅λλ€. μλ₯Ό λ€μ΄, Swiftμ Dictionaryλ ν€ νμ μ΄ Hashable νλ‘ν μ½μ μ€μν΄μΌ ν©λλ€.
λ€μμ νμ μ μ½μ μ¬μ©ν μμ μ λλ€:
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
μ΄ ν¨μλ Tκ° Equatable νλ‘ν μ½μ μ€μνλ νμ μ΄μ΄μΌλ§ μ¬μ©ν μ μμ΅λλ€. λλΆμ == μ°μ°μλ₯Ό μ¬μ©ν μ μκ² λ©λλ€:
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
// doubleIndexλ nil(λ°°μ΄μ 9.3μ΄ μκΈ° λλ¬Έ)
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
// stringIndexλ 2μ κ°μ κ°μ§ Int?
π μ°κ΄λ νμ (Associated Types)
νλ‘ν μ½μ μ μν λ νλ μ΄μμ μ°κ΄λ νμ μ μ μΈνλ κ²μ΄ μ μ©ν μ μμ΅λλ€. μ°κ΄λ νμ μ νλ‘ν μ½μ μΌλΆλ‘ μ¬μ©λλ νμ μ λν νλ μ΄μ€νλ μ΄λ¦μ μ 곡ν©λλ€.
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
μ΄ νλ‘ν μ½μ 컨ν μ΄λκ° μ΄λ€ νμ μ νλͺ©μ μ μ₯ν μ§ μ§μ νμ§ μμ΅λλ€. λμ , νλ‘ν μ½μ μ±ννλ νμ μ΄ Itemμ μ€μ νμ μ μ§μ ν©λλ€:
struct IntStack: Container {
// μλ IntStack ꡬν
var items: [Int] = []
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// Container νλ‘ν μ½ μ€μ
typealias Item = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
μ λλ¦ νμ μμλ μ°κ΄ νμ μ΄ μλμΌλ‘ μΆλ‘ λ©λλ€:
struct Stack<Element>: Container {
// μλ Stack<Element> ꡬν
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
// Container νλ‘ν μ½ μ€μ
mutating func append(_ item: Element) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
}
μ°κ΄λ νμ μ μ μ½ μΆκ°νκΈ°
μ°κ΄λ νμ μλ νμ μ μ½μ μΆκ°ν μ μμ΅λλ€:
protocol Container {
associatedtype Item: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
π μ λλ¦ Where μ (Generic Where Clauses)
νμ μ μ½ μΈμλ, μ λλ¦ ν¨μλ νμ μ μꡬμ¬νμ λ μΈλΆμ μΌλ‘ μ μνκΈ° μν΄ μ λλ¦ where μ μ μ¬μ©ν μ μμ΅λλ€:
func allItemsMatch<C1: Container, C2: Container>
(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
// λ 컨ν
μ΄λμ νλͺ© μκ° κ°μμ§ νμΈ
if someContainer.count != anotherContainer.count {
return false
}
// κ° νλͺ©μ΄ λμΌνμ§ νμΈ
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// λͺ¨λ νλͺ©μ΄ μΌμΉνλ©΄ true λ°ν
return true
}
μ΄ ν¨μλ λ 컨ν μ΄λκ° κ°μ νλͺ© νμ μ κ°μ§κ³ μμΌλ©°, κ·Έ νλͺ© νμ μ΄ Equatableμ μ€μν΄μΌ νλ€λ μ μ½μ μ€μ ν©λλ€:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
var arrayOfStrings = ["uno", "dos", "tres"]
if allItemsMatch(stackOfStrings, arrayOfStrings) {
print("λͺ¨λ νλͺ©μ΄ μΌμΉν©λλ€.")
} else {
print("μΌμΉνμ§ μλ νλͺ©μ΄ μμ΅λλ€.")
}
// "λͺ¨λ νλͺ©μ΄ μΌμΉν©λλ€." μΆλ ₯
Where μ μ΄ μλ νμ₯
where μ μ μ¬μ©ν΄ μ λλ¦ νμ μ νμ₯ν μλ μμ΅λλ€:
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
μ΄ νμ₯μ Stackμ μμκ° Equatableμ μ€μν λλ§ μ μ©λ©λλ€:
if stackOfStrings.isTop("tres") {
print("μ΅μμ μμλ tresμ
λλ€.")
} else {
print("μ΅μμ μμλ λ€λ₯Έ κ²μ
λλ€.")
}
// "μ΅μμ μμλ tresμ
λλ€." μΆλ ₯
νλ‘ν μ½ νμ₯μλ where μ μ μ¬μ©ν μ μμ΅λλ€:
extension Container where Item: Equatable {
func startsWith(_ item: Item) -> Bool {
return count >= 1 && self[0] == item
}
}
λν, νΉμ νμ μλ§ μ μ©λλ νμ₯λ κ°λ₯ν©λλ€:
extension Container where Item == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
print([1260.0, 1200.0, 98.6, 37.0].average())
// 648.9 μΆλ ₯
μν©λ³ Where μ
μ λλ¦ νμ μ 컨ν μ€νΈμμ μ΄λ―Έ μμ μ€μΈ κ²½μ°, κ°λ³ λ©μλλ μμ±μ where μ μ μ μ©ν μλ μμ΅λλ€:
extension Container {
func average() -> Double where Item == Int {
var sum = 0.0
for index in 0..<count {
sum += Double(self[index])
}
return sum / Double(count)
}
func endsWith(_ item: Item) -> Bool where Item: Equatable {
return count >= 1 && self[count-1] == item
}
}
π μ λλ¦ μλΈμ€ν¬λ¦½νΈ
μλΈμ€ν¬λ¦½νΈλ μ λλ¦μΌλ‘ μ μν μ μμΌλ©°, μ λλ¦ where μ μ ν¬ν¨ν μ μμ΅λλ€:
extension Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int {
var result: [Item] = []
for index in indices {
result.append(self[index])
}
return result
}
}
μ΄ μλΈμ€ν¬λ¦½νΈλ μ μ μνμ€λ₯Ό λ°μ ν΄λΉ μΈλ±μ€μ μλ νλͺ©λ€μ λ°°μ΄μ λ°νν©λλ€.
π μ 리
Swiftμ μ λλ¦μ νμ μμ μ±μ μ μ§νλ©΄μ μ½λ μ¬μ¬μ©μ±μ λμ΄λ κ°λ ₯ν κΈ°λ₯μ λλ€. μ λλ¦μ ν΅ν΄:
- μ½λ μ€λ³΅μ μ€μΌ μ μμ΅λλ€ - λ€μν νμ μ λν΄ λμΌν κΈ°λ₯μ μ 곡νλ μ½λλ₯Ό ν λ²λ§ μμ±νλ©΄ λ©λλ€.
- νμ μμ μ±μ 보μ₯ν©λλ€ - μ»΄νμΌ μμ μ νμ κ²μ¬κ° μ΄λ£¨μ΄μ Έ λ°νμ μ€λ₯λ₯Ό μ€μΌ μ μμ΅λλ€.
- μ μ°ν APIλ₯Ό μ€κ³ν μ μμ΅λλ€ - μ¬μ©μκ° λ€μν νμ κ³Ό ν¨κ» APIλ₯Ό μ¬μ©ν μ μλλ‘ ν©λλ€.
- μ±λ₯ μ ν μμ΄ μΆμνλ₯Ό μ 곡ν©λλ€ - μ λλ¦μ μ»΄νμΌ μκ°μ ν΄κ²°λλ―λ‘ λ°νμ μ±λ₯μ μν₯μ μ£Όμ§ μμ΅λλ€.
'π₯ Bread Basics > Swift' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Swift 곡μ λ¬Έμ μ 리 - μ κ·Ό μ μ΄ (Access Control) (0) | 2025.04.13 |
---|---|
Swift 곡μ λ¬Έμ μ 리 - λ©λͺ¨λ¦¬ μμ μ± (Memory Safety) (0) | 2025.04.13 |
Swift 곡μ λ¬Έμ μ 리 - μλ μ°Έμ‘° μΉ΄μ΄ν (Automatic Reference Counting) (0) | 2025.04.13 |
Swift 곡μ λ¬Έμ μ 리 - λΆν¬λͺ ν νμ (Opaque Types) (0) | 2025.04.13 |
Swift 곡μ λ¬Έμ μ 리 - νλ‘ν μ½ (Protocols) (0) | 2025.04.13 |
Swift 곡μ λ¬Έμ μ 리 - νμ₯ (Extensions) (0) | 2025.04.13 |
Swift 곡μ λ¬Έμ μ 리 - μ€μ²©λ νμ (Nested Types) (1) | 2025.04.12 |
Swift 곡μ λ¬Έμ μ 리 - νμ μΊμ€ν (Type Casting) (0) | 2025.04.12 |