๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โŒจ๏ธ Language/swift

[Swift] ์ œ๋„ค๋ฆญ

by hyebin (Helia) 2024. 4. 2.
๋ฐ˜์‘ํ˜•

์ œ๋„ค๋ฆญ(Generics)

์œ ์—ฐํ•˜๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์™€ ํƒ€์ž…์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ

์ธ์ž๊ฐ’์˜ ํƒ€์ž…๋งŒ ๋‹ค๋ฅด๊ณ  ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

 

์ œ๋„ค๋ฆญ ํ•จ์ˆ˜(Generic Functions)

ํ•จ์ˆ˜๋ช… ๋’ค์— ํƒ€์ž… ์ด๋ฆ„ placeholder์ธ T๋ฅผ ์„ ์–ธํ•˜๊ณ  a,b ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ T๋กœ ์„ ์–ธ

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 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"

 

ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ(Type Parameters)

placeholder ํƒ€์ž…์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ•˜๊ณ  ํ•จ์ˆ˜๋ช… ๋ฐ”๋กœ ๋’ค์— ์ ์–ด์ค€ ํ›„ ๊บฝ์‡„๋กœ ๋ฌถ์–ด ์‚ฌ์šฉ

ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„ ์ง“๊ธฐ

element ๊ฐ„์˜ ์ƒ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์˜๋ฏธ ์žˆ๋Š” ์ด๋ฆ„์„ ๋งˆ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ

๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ T, U, V์™€ ๊ฐ™์€ ๋‹จ์ผ ๋ฌธ์ž๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ

 

์ œ๋„ค๋ฆญ ํƒ€์ž…

์ œ๋„ค๋ฆญ ํ•จ์ˆ˜์— ์ถ”๊ฐ€๋กœ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •์˜ ๊ฐ€๋Šฅ

์ต์Šคํ…์…˜์„ ์ด์šฉํ•ด ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Œ

struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

extension Stack {
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

 

ํƒ€์ž… ์ œํ•œ

ํŠน์ • ํƒ€์ž…์ด ๋ฐ˜๋“œ์‹œ ์–ด๋–ค ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ผ์•ผํ•˜๋Š” ๊ฒฝ์šฐ ํŠน์ • ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๊ฑฐ๋‚˜ ํ•ฉ์„ฑํ•˜๋„๋ก ๋ช…์‹œ ๊ฐ€๋Šฅ

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

 

์—ฐ๊ด€ ํƒ€์ž…

ํ”„๋กœํ† ์ฝœ์˜ ์ผ๋ถ€๋ถ„์œผ๋กœ ํƒ€์ž…์— placeholder ์ด๋ฆ„์„ ๋ถ€์—ฌ

ํŠน์ • ํƒ€์ž…์„ ๋™์ ์œผ๋กœ ์ง€์ •ํ•ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ

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

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]
    }
}

 

์ œ๋„ค๋ฆญ์˜ Where์ ˆ

๊ธฐ๋ณธ ์ œ๋„ค๋ฆญ, ์ œ๋„ค๋ฆญ์˜ ์ต์Šคํ…์…˜, ์—ฐ๊ด€ํƒ€์ž…, ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ์—์„œ๋„ where ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด ์กฐ๊ฑด์„ ๊ฑธ ์ˆ˜ ์žˆ์Œ

func allItemsMatch<C1: Container, C2: Container>
    (_ someContainer: C1, _ anotherContainer: C2) -> Bool
    where C1.Item == C2.Item, C1.Item: Equatable {

        // Check that both containers contain the same number of items.
        if someContainer.count != anotherContainer.count {
            return false
        }

        // Check each pair of items to see if they're equivalent.
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }

        // All items match, so return true.
        return true
}
๋ฐ˜์‘ํ˜•