상세 컨텐츠

λ³Έλ¬Έ 제λͺ©

[ Swift 기초 문법 ] μ œλ„€λ¦­(Generics)

🍎 iOS/Swift

by AHN.Jihyeon 2024. 7. 31. 17:17

λ³Έλ¬Έ

 


πŸ’¬  μ œλ„€λ¦­ 문법이 ν•„μš”ν•œ 이유

νƒ€μž…λ§Œ λ‹€λ₯΄κ³  κ΅¬ν˜„ λ‚΄μš©μ΄ λ™μΌν•œλ° ꡳ이 ν•¨μˆ˜λ₯Ό μΆ”κ°€μ μœΌλ‘œ λ°˜λ³΅ν•΄μ„œ λ§Œλ“€μ–΄μ•Όν•  ν•„μš”κ°€ μžˆμ„κΉŒ!

 

μ œλ„€λ¦­μ΄ μ—†λ‹€λ©΄ ν•¨μˆ˜(뿐만 μ•„λ‹ˆλΌ 클래슀, ꡬ쑰체, μ—΄κ±°ν˜• 등도 κ°€λŠ₯) νƒ€μž…λ§ˆλ‹€ λͺ¨λ“  경우λ₯Ό λ‹€ μ •μ˜ν•΄μ•Όν•΄μ„œ 

개발자의 할일이 λ§Žμ•„μ§„λ‹€. -> μœ μ§€λ³΄μˆ˜/ μž¬μ‚¬μš©μ„±μ΄ 어렀움

 

즉, ν•¨μˆ˜λ₯Ό ν•˜λ‚˜λ§Œ κ΅¬ν˜„ν•˜λ©΄ 내뢀에 μžˆλŠ” νƒ€μž…μ€ μ–Έμ œλ“ μ§€ λ°”κΏ”μ„œ μ‚¬μš© κ°€λŠ₯

-> μ œλ„€λ¦­μ΄ μ—†λ‹€λ©΄ ν•¨μˆ˜λ₯Ό λͺ¨λ“  νƒ€μž…λ§ˆλ‹€ λ‹€μ‹œ μ •μ˜ ν•΄μ„œ μ‚¬μš©ν•΄μ•Όν•œλ‹€.

-> μ—¬λŸ¬λ²ˆ μ€‘λ³΅ν•΄μ„œ κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” ν•„μš”κ°€ 없어진닀.  

 

νƒ€μž… νŒŒλΌλ―Έν„°λŠ” ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ νŒŒλΌλ―Έν„° ν˜•μ‹μ΄λ‚˜ λ¦¬ν„΄ν˜•μœΌλ‘œ μ‚¬μš©λœλ‹€. ν•¨μˆ˜ λ°”λ””μ—μ„œ μ‚¬μš©λ„ κ°€λŠ₯.

보톡 Tλ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ λ‹€λ₯Έ 이름 μ‚¬μš©λ„ κ°€λŠ₯. 2개 이상도 κ°€λŠ₯. 

 

 

 

πŸ”Ž  1 . μ œλ„€λ¦­ ν•¨μˆ˜ μ •μ˜


ν•¨μˆ˜ 이름 μ˜†μ— <> λ₯Ό μ‚¬μš©ν•΄ νŒŒλΌλ―Έν„° Tλ₯Ό 적어쀀닀. 보톡 Type을 μ˜λ―Έν•˜λŠ” Tλ₯Ό μ‚¬μš©ν•œλ‹€. 

<>μ•ˆμ— μžˆλŠ” TλΌλŠ” 문자λ₯Ό νƒ€μž…νŒŒλΌλ―Έν„°λ‘œ μ •μ˜ν•  λ•Œ μ‚¬μš©ν• κ±°λΌλŠ” 의미.

μ„œλ‘œ λ‹€λ₯Έ νƒ€μž…μ„ μ‚¬μš©ν•  λ•Œλ„ μžˆλ‹€. 

 

μ œλ„€λ¦­μ€ μ‹€μ œ νƒ€μž… 이름을 μ¨μ£ΌλŠ” λŒ€μ‹ μ— placeholderλ₯Ό μ‚¬μš©ν•œλ‹€. [ eg: T, V, U ]

placeholderλŠ” νƒ€μž…μ˜ μ’…λ₯˜λ₯Ό μ•Œλ €μ£Όμ§€ μ•Šμ§€λ§Œ μ–΄λ–€ νƒ€μž…μ΄λΌλŠ” 것은 μ•Œλ €μ€€λ‹€.

placeholder의 μ‹€μ œ νƒ€μž…μ€ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” μˆœκ°„ κ²°μ •λœλ‹€.

ν•˜λ‚˜μ˜ νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό 갖지 μ•Šκ³  μ—¬λŸ¬ 개의 νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό κ°–κ³  μ‹Άλ‹€λ©΄ ν™€ν™”μ‚΄κ΄„ν˜Έ 기호 μ•ˆμͺ½μ— μ‰Όν‘œλ‘œ λΆ„λ¦¬ν•œ μ—¬λŸ¬ 개의 νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό 지정해쀄 수 μžˆλ‹€. [ eg: <T, U> ]

 

//예제1) 배열을 좜λ ₯
func printArray<T>(array: [T]){
	//ν•¨μˆ˜ μ‹€ν–‰ λ‚΄μš© μž‘μ„±
}


//예제2) 2가지 νƒ€μž…μ„ μ‚¬μš©ν•  경우 
func swapTwoValues<T, A>(_ a: inout T, _ b: inout A) {
   //ν•¨μˆ˜ μ‹€ν–‰ λ‚΄μš© μž‘μ„±
}

 

 

1. μš°λ¦¬κ°€ κ·Έλ™μ•ˆ κ°„λ‹¨ν•˜κ²Œ μ‚¬μš©ν•΄μ™”λ˜ λ°°μ—΄μ˜ μ •κ·œ 문법을 λ‹€μ‹œ 보면 μ œλ„€λ¦­μœΌλ‘œ λ˜μ–΄μžˆμ—ˆλ‹€. 

Array<Element>둜 μ •μ˜ λ˜μ–΄ μžˆμ–΄μ„œ Element 뢀뢄에 String, Int 등을 λ„£μ–΄ μ‚¬μš©ν•  수 μžˆμ—ˆλ˜ 것!!

 

 

2. λ”•μ…”λ„ˆλ¦¬ Dictionary<key, value>도 λ‹€μ‹œ 보면 μ œλ„€λ¦­μ΄λ‹€. 

μ„œλ‘œ λ‹€λ₯Έ 두 νƒ€μž… key와 valueλ₯Ό μ‚¬μš©ν•  수 있던 것. 

 

 

3. μ˜΅μ…”λ„ νƒ€μž…λ„ μ œλ„€λ¦­μ΄λ‹€. 

 

 

4. κ³ μ°¨ν•¨μˆ˜ map도 μ œλ„€λ¦­μ΄λ‹€

μ •μˆ˜λ₯Ό String으둜 λ°”κΏ€ 수 있고  Doubleλ‘œλ„ λ°”κΏ€ 수 μžˆμ—ˆλ˜ 것!

 

 

/*
inout ν‚€μ›Œλ“œλŠ” ν•¨μˆ˜ λ‚΄μ—μ„œ λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬λœ 값을 λ³€κ²½ν•˜κ³ , 
이λ₯Ό ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œλ„ λ°˜μ˜ν•  수 μžˆλ„λ‘ ν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€. 
이λ₯Ό 톡해 ν•¨μˆ˜ λ‚΄μ—μ„œ λ§€κ°œλ³€μˆ˜μ˜ 값을 직접 μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

inout ν‚€μ›Œλ“œ μ‚¬μš© 방법:
1. λ§€κ°œλ³€μˆ˜μ— inout ν‚€μ›Œλ“œλ₯Ό λΆ™μ—¬ μ„ μ–Έν•©λ‹ˆλ‹€.
2. ν•¨μˆ˜ 호좜 μ‹œ λ§€κ°œλ³€μˆ˜λ₯Ό & 기호둜 μ „λ‹¬ν•˜μ—¬ ν•΄λ‹Ή 값을 참쑰둜 μ „λ‹¬ν•©λ‹ˆλ‹€.
*/


// ν•¨μˆ˜ μ •μ˜
func increment(_ value: inout Int) {
    value += 1
}

var number = 5
print("Before increment: \(number)") // 좜λ ₯: Before increment: 5

// ν•¨μˆ˜ 호좜 μ‹œ λ§€κ°œλ³€μˆ˜μ— &λ₯Ό μ‚¬μš©ν•˜μ—¬ λ³€μˆ˜μ˜ μ°Έμ‘°λ₯Ό 전달
increment(&number)

print("After increment: \(number)") // 좜λ ₯: After increment: 6

 

 

 

 

 

 

πŸ”Ž  2. μ œλ„€λ¦­κ³Ό ꡬ쑰체/ 클래슀/ μ—΄κ±°ν˜•


//기쑴 ꡬ쑰체
struct Member {
	var members: [String] = []
}


//struct GenericMember<T> {
	var members: [T] = []
}

var member1 = GenericMember(members: ["a", "b", "c"]) //μ΄μ œλΆ€ν„° String νƒ€μž…μœΌλ‘œ κ²°μ •λœλ‹€. 
var member2 = GenericMember(members: [1, 2, 3])       //μ΄μ œλΆ€ν„° Int νƒ€μž…μœΌλ‘œ κ²°μ •λœλ‹€.

 

 

μ—΄κ±°ν˜•μ€ 연관값을 κ°€μ§ˆ λ•Œλ§Œ μ‚¬μš©ν•  수 μžˆλ‹€.

 

 

 

 

 

πŸ”Ž 3. ν”„λ‘œν† μ½œμ—μ„œμ˜ μ œλ„€λ¦­ μ‚¬μš©


μ œλ„€λ¦­μ„ μ‚¬μš©ν•΄ ν”„λ‘œν† μ½œμ„ μ„ μ–Έν•˜ν•  λ•ŒλŠ” 기쑴의 <T>κ°€ μ•„λ‹Œ

assoociatedtype(μ—°κ΄€νƒ€μž…) + νƒ€μž… νŒŒλΌλ―Έν„°(μ²«κΈ€μž λŒ€λ¬Έμž)
ν˜•μ‹μœΌλ‘œ μ‚¬μš©ν•œλ‹€. 

protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

 

 

μ—°κ΄€ν˜•μ‹μ΄ μ„ μ–Έλœ ν”„λ‘œν† μ½œ 채택 μ‹œ associatedtype을 μ‹€μ œ νƒ€μž…μœΌλ‘œ κ΅¬μ²΄ν™”ν•œλ‹€. 

typealias둜 ν˜•μ‹μ„ λͺ…μ‹œ ν•œλ‹€. (μƒλž΅ κ°€λŠ₯)

struct IntStack: Container {
    // original IntStack implementation
    var items: [Int] = []
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformance to the Container protocol
    typealias Item = Int
    mutating func append(_ item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

 

 

 

μ œλ„€λ¦­ ν”„λ‘œν† μ½œμ— μ œμ•½μ΄ˆκ±΄ μΆ”κ°€ 

'Item은 Equatable ν”„λ‘œν† μ½œμ„ μ±„νƒν•œ νƒ€μž…λ§Œ μ •μ˜ κ°€λŠ₯ν•˜λ‹€'의 의미. 

 

protocol Container {
    associatedtype Item: Equatable
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

 

 

 

 

 

πŸ”— Reference 


 

κ΄€λ ¨κΈ€ 더보기