ν‹°μŠ€ν† λ¦¬ λ·°

λ°˜μ‘ν˜•

img


🎯 μ œλ„€λ¦­(Generic) in Swift


πŸ§‘πŸ»β€πŸ’» What - μ œλ„€λ¦­μ΄λž€?


  • SwiftλŠ” μ–΄λ–€ λ³€μˆ˜λ‚˜ μƒμˆ˜, ν˜Ήμ€ ν•¨μˆ˜(λ©”μ†Œλ“œ)의 νŒŒλΌλ―Έν„° 등을 κ΅¬ν˜„ν•  λ•Œ νƒ€μž…μ„ μ§€μ •ν•©λ‹ˆλ‹€. νƒ€μž…μ„ λͺ…μ‹œν•¨μœΌλ‘œμ¨ μ»΄νŒŒμΌλŸ¬μ—κ²Œ ν•΄λ‹Ή κ°’μ˜ νƒ€μž…μ„ λͺ…ν™•νžˆ μ„€λͺ…ν•΄μ£Όκ³ , μ½”λ“œλ₯Ό μ½λŠ” κ°œλ°œμžλ“€μ˜ μž…μž₯μ—μ„œ ν•΄λ‹Ή κ°’μ˜ νŠΉμ„±μ„ 더 잘 이해할 수 μžˆλ„λ‘ λ„μ™€μ€λ‹ˆλ‹€. λ¬Όλ‘  νƒ€μž… μΆ”λ‘  κΈ°λŠ₯을 톡해 νƒ€μž… λͺ…μ‹œλ₯Ό μƒλž΅ν•΄μ€„ 수 μžˆμ§€λ§Œ νŠΉμ • νƒ€μž…μ΄ ν™•μ •λ˜μ–΄μ•Ό ν•˜λŠ” 것은 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€.

    이런 μƒν™©μ—μ„œ λ‘œμ§μ€ μ™„μ „νžˆ 같은데 μž…λ ₯κ°’μ˜ νƒ€μž…λ§Œ λ‹€λ₯Έ 경우 μ–΄λ–»κ²Œ λ˜μ–΄μ•Ό ν• κΉŒμš”? 일반적으둜 μ˜€λ²„λ‘œλ”©(over loading)으둜 ν•¨μˆ˜λ₯Ό νƒ€μž…λ“€μ— 맞게 μ •μ˜ν•  수 μžˆμ§€λ§Œ 그것 μ—­μ‹œ λ¬΄μ˜λ―Έν•œ μ½”λ“œμ˜ 반볡이 λ©λ‹ˆλ‹€.

    SwiftλŠ” μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ” Genericμ΄λΌλŠ” κΈ°λŠ₯을 가지고 μžˆμŠ΅λ‹ˆλ‹€. νŠΉμ • νƒ€μž…μ„ 미리 μ§€μ •ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ‚¬μš©ν•  λ•Œ ν•„μš”ν•œ νƒ€μž…μ„ μ„ μ–Έν•΄μ£ΌλŠ” ν˜•νƒœλ‘œ νƒ€μž…μ„ μΌλ°˜ν™” ν•˜μ—¬ μ„ μ–Έν•œλ‹€κ³  ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    μ˜ˆμ‹œλ₯Ό 톡해 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€!


πŸ“š Why - μ œλ„€λ¦­μ΄ ν•„μš”ν•œ 이유


  • μš°μ„  두 Int값을 κ΅ν™˜ν•˜λŠ” λ©”μ†Œλ“œλ₯Ό μ„ μ–Έν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.


    func swapTwoInts(_ a: inout Int, _ b: inout Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

    inout이 이해가 μ–΄λ €μš°μ‹  뢄듀은 μ‰½κ²Œ μƒκ°ν•΄μ„œ 두 μž…λ ₯ νŒŒλΌλ―Έν„° a, bλ₯Ό κ΅ν™˜ν•΄μ£ΌλŠ” λ©”μ†Œλ“œλΌκ³  μƒκ°ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€!

    이 λ©”μ†Œλ“œλ₯Ό 잘 μ‚¬μš©ν•˜κ³  μžˆμ—ˆλŠ”λ° Intκ°€ μ•„λ‹Œ String을 κ΅ν™˜ν•΄μ•Όν•  λ©”μ†Œλ“œκ°€ ν•„μš”ν•˜λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒμš”?

    μ•„λž˜μ™€ 같이 ν•¨μˆ˜λ₯Ό 또 μ •μ˜ν•©λ‹ˆλ‹€.


    func swapTwoStrings(_ a: inout String, _ b: inout String) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

    둜직이 μ™„μ „νžˆ κ°™μ§€λ§Œ νŒŒλΌλ―Έν„°λ₯Ό μœ„ν•΄ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό μ •μ˜ν–ˆμŠ΅λ‹ˆλ‹€. λ¬Έμ œκ°€ ν•΄κ²°λ¬μœΌλ‹ˆ 또 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ‹€κ°€ μ΄λ²ˆμ—λŠ” Doubleν˜•μ˜ κ΅ν™˜μ΄ ν•„μš”ν•©λ‹ˆλ‹€. 그럼 λ‹Ήμ—°νžˆ 또 μ •μ˜λ₯Ό ν•΄μ•Όκ² μ£ ?


    func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

    정상 μž‘λ™ μ—¬λΆ€λ₯Ό λ– λ‚˜μ„œ 이런 μ‹μ˜ κ΅¬ν˜„μ€ λ¬΄μ˜λ―Έν•œ μ½”λ“œμ˜ λ°˜λ³΅μ„ λΆˆλŸ¬μ˜΅λ‹ˆλ‹€. N개의 νƒ€μž…μ„ μ‚¬μš©ν•œλ‹€λ©΄ 같은 λ©”μ†Œλ“œλ₯Ό N개 λ§Œλ“€μ–΄μ•Ό ν•˜λŠ” λΆˆνŽΈν•¨μ΄ μžˆλŠ” 것이죠!


πŸ›  How - Generic μ‚¬μš©λ²•


  • 그럼 μœ„μ˜ μ˜ˆμ‹œλ₯Ό ν•œλ²ˆμ— μ„ μ–Έν•  방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€! μ•„λž˜μ™€ 같이 λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•΄μ€λ‹ˆλ‹€.


    func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

    기쑴에 Int, String λ“±μœΌλ‘œ μ„ μ–Έλ˜μ–΄ μžˆμ—ˆλ˜ νƒ€μž…μ— TλΌλŠ” μΌλ°˜ν™”λœ νƒ€μž…μ„ λ„£μ–΄μ£Όκ³ , λŒ€μ‹ μ— λ©”μ†Œλ“œ 이름 μ˜†μ— <T>λΌλŠ” λ§ˆν‚Ήμ„ ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€. T에 무엇이 듀어가냐에 따라 μœ„μ˜ ν•¨μˆ˜λŠ” T둜 ν‘œκΈ°λœ νƒ€μž…μ— μ‚¬μš©ν•˜κ³  싢은 νƒ€μž…μ„ μΌκ΄„μ μœΌλ‘œ μ„ μ–Έν•΄μ£ΌλŠ” 것이죠!

    이제 μœ„μ— μ •μ˜λœ λ©”μ†Œλ“œλ‘œ 값을 λ³€κ²½ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.


    var someInt = 3
    var anotherInt = 107
    swapTwoValues(&someInt, &anotherInt)
    // someInt is now 107, and anotherInt is now 3
    
    var someString = "hello"
    var anotherString = "world"
    swapTwoValues(&someString, &anotherString)
    // someString is now "world", and anotherString is now "hello"

    νŠΉλ³„νžˆ νƒ€μž…μ„ λͺ…μ‹œν•  ν•„μš” 없이 μž…λ ₯된 κ°’μ˜ νƒ€μž…μ„ 톡해 μžλ™μ μœΌλ‘œ T 에 각각 Int , String 을 ν• λ‹Ήν•˜μ—¬ μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.

    μ΄λ ‡κ²Œ 보면 λ‚―μ„€ 수 μžˆμ§€λ§Œ 사싀 κ·Έλ™μ•ˆ μš°λ¦¬λŠ” Generic κΈ°λŠ₯을 많이 μ‚¬μš©ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

    λŒ€ν‘œμ μΈ 것이 Array, Dictionary μž…λ‹ˆλ‹€. 배열을 μ •μ˜ν•  λ•Œ νƒ€μž…μ„ μ§€μ •ν•΄μ„œ μ–΄λ–€ νƒ€μž…μ˜ 배열인지 λͺ…μ‹œν–ˆμ—ˆλŠ”λ° 이 κ°œλ…μ΄ λ°”λ‘œ Genericμž…λ‹ˆλ‹€. 배열을 μ‚¬μš©ν•˜λŠ” μ˜ˆμ‹œλ‘œ Stack κ΅¬ν˜„μ„ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.


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

    μœ„μ˜ Stack의 경우 자료ꡬ쑰의 ν•˜λ‚˜λ‘œ νƒ€μž…μ΄ νŠΉμ •λ˜λ©΄ μ•ˆλ©λ‹ˆλ‹€. λ‹€μ‹œ λ§ν•˜λ©΄ Int 만 λ˜λŠ” μŠ€νƒμ€ νš¨μœ¨μ„±μ΄ 떨어지겠죠? κ·Έλž˜μ„œ μœ„μ™€ 같이 Generic으둜 μ„ μ–Έν•˜μ—¬ μ‚¬μš©ν•©λ‹ˆλ‹€.


πŸ§— One more step - ν•œκ±ΈμŒ 더


  • Generic이 만λŠ₯인 것 κ°™μ§€λ§Œ 사싀 생각해보면 큰 였λ₯˜μ˜ κ°€λŠ₯성을 λ‚΄ν¬ν•˜κ³  μžˆκΈ°λ„ ν•©λ‹ˆλ‹€.


    func newMultiply<T>(param1: T, param2: T) -> T {
        return param1 * param2 * 2
    }

    μœ„μ˜ λ©”μ†Œλ“œλŠ” μž…λ ₯ 받은 parameterλ₯Ό κ³±ν•˜λŠ” 연산이 있기 λ•Œλ¬Έμ— λ‹Ήμ—°νžˆ κ³±ν•˜κΈ° 연산이 κ°€λŠ₯ν•œ νƒ€μž…μ΄ λ“€μ–΄μ™€μ•Όν•©λ‹ˆλ‹€. Int, Double, Float λ“±μ˜ νƒ€μž…μ΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 이런 λ‹€μ–‘ν•œ νƒ€μž…μ„ μœ„ν•΄ Generic으둜 선언이 된 κ²ƒμΈλ°μš”, λ§Œμ•½μ— 이 Generic에 String이 λ“€μ–΄μ˜€λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”? μ—°μ‚° μžμ²΄κ°€ μ„±λ¦½ν•˜μ§€ μ•Šκ²Œ λ©λ‹ˆλ‹€.

    κ·Έλž˜μ„œ XCodeλŠ” μœ„μ˜ μ •μ˜κ°€ λΆ€μ •ν™•ν•˜λ‹€λŠ” 메세지λ₯Ό μ€λ‹ˆλ‹€. μΆ©λΆ„ν•œ 정보가 μ—†λ‹€λŠ” 것이죠. 이럴 λ•Œ ν•„μš”ν•œ 것이 μ œλ„€λ¦­ν•œ νƒ€μž…μ„ ꡬ체화 ν•΄μ£ΌλŠ” κ²ƒμž…λ‹ˆλ‹€.


    func newMultiply<T: BinaryInteger>(param1: T, param2: T) -> T {
        return param1 * param2 * 2
    }

    μœ„μ™€ 같이 Generic νƒ€μž…μΈ Tλ₯Ό λ‹¨μˆœνžˆ μ„ μ–Έν•΄μ£ΌλŠ” 것이 μ•„λ‹ˆλΌ BinaryInteger ν”„λ‘œν† μ½œμ„ λ”°λ₯΄κ²Œ ν•΄μ£Όλ©΄ 였λ₯˜κ°€ ν•΄κ²°λ©λ‹ˆλ‹€. μ΄λ ‡κ²Œ νƒ€μž…μ— μ œμ•½μ„ μ£ΌλŠ” 것을 νƒ€μž… μ œμ•½(Type Constaints) 이라고 ν•˜λ©° μ΄λŸ¬ν•œ μ œμ•½μ€ 클래슀 νƒ€μž… λ˜λŠ” ν”„λ‘œν† μ½œλ‘œλ§Œ μ„€μ • κ°€λŠ₯ν•©λ‹ˆλ‹€. νŠΉμ • 클래슀λ₯Ό μƒμ†λ°›λŠ” νƒ€μž…μ΄μ–΄μ•Όν•˜κ±°λ‚˜ νŠΉμ • ν”„λ‘œν† μ½œμ„ μ±„νƒν•œ νƒ€μž…μ΄μ–΄μ•Όν•œλ‹€λŠ” μ œμ•½μ„ μ„€μ •ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.


  • μ œλ„€λ¦­ νƒ€μž…μ€ ν•œκ°œκ°€ μ•„λ‹ˆλΌ μ—¬λŸ¬κ°œ 섀정될 수 μžˆμŠ΅λ‹ˆλ‹€.

    func someMethod<T, U, V> (param1: T, param2: U, param3: V) { ... }

    처럼 μ‰Όν‘œ(,)λ₯Ό 톡해 μ—¬λŸ¬κ°œ μ„ μ–Έν•  수 μžˆμŠ΅λ‹ˆλ‹€.


Reference: https://docs.swift.org/swift-book/LanguageGuide/Generics.html

λ°˜μ‘ν˜•
λŒ“κΈ€
λ°˜μ‘ν˜•
곡지사항
μ΅œκ·Όμ— 올라온 κΈ€
μ΅œκ·Όμ— 달린 λŒ“κΈ€
Total
Today
Yesterday
링크
TAG more
Β«   2024/11   Β»
일 μ›” ν™” 수 λͺ© 금 ν† 
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
κΈ€ 보관함