๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/WWDC

[WWDC 2022] ์ œ๋„ˆ๋ฆญ๊ณผ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•ด ์ฝ”๋“œ ์ถ”์ƒํ™”ํ•˜๊ธฐ (feat. some,any) (Embrace Swift generics)

by Fomagran ๐Ÿ’ป 2022. 7. 10.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋Š˜์€ WWDC 2022์—์„œ ์ œ๋„ˆ๋ฆญ๊ณผ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •์„(?)์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ถ”์ƒํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋‹ค๋ฃฌ Embrace Swift generics ์„ธ์…˜์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~

 

(์ œ ๋ฐฉ์‹๋Œ€๋กœ ํ•ด์„ํ•˜์—ฌ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ˆ ํ‹€๋ฆฐ ์ ์ด๋‚˜ ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“  ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”!)


Model with concrete types

 

๊ฐ€์žฅ ๋จผ์ € ์–ด๋– ํ•œ ๊ฒƒ๋„ ์ถ”์ƒํ™”๋‚˜ ์ œ๋„ˆ๋ฆญ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ์ฆ‰, ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ์ด์šฉํ•ด์„œ ๋†์žฅ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

๋†์žฅ์— ์†Œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , ๊ทธ ์†Œ๋Š” ๊ฑด์ดˆ(Hay)๋ฅผ ๋จน๋Š” struct๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

struct Cow {
    func eat(_ food:Hay) {...}
}

 

์ด์ œ ์†Œ๊ฐ€ ๋จน๋Š” ๊ฑด์ดˆ๋Š” ์ž๋ผ๋ฉด ์•ŒํŒ”ํŒŒ(Alfalfa)๋ผ๋Š” ์‹๋ฌผ์ด ๋˜๋Š” struct๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

struct Hay {
    static func grow() -> Alfalfa {}
}

 

์œ„์—์„œ ๊ฑด์ดˆ๊ฐ€ ์ž๋ผ๋ฉด ์•ŒํŒ”ํŒŒ๊ฐ€ ๋œ๋‹ค๊ณ  ํ–ˆ์ฃ ? ๊ณ ๋กœ ์•ŒํŒ”ํŒŒ๋ฅผ ์ˆ˜ํ™•ํ•˜๋ฉด ๊ฑด์ดˆ๊ฐ€ ๋˜๋Š” ์•ŒํŒ”ํŒŒ struct๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

struct Alfalfa {
    func havest() -> Hay {}
}

 

๋งˆ์ง€๋ง‰์œผ๋กœ ์œ„ ์„ธ ๊ฐœ์˜ struct๋ฅผ ์ด์šฉํ•˜์—ฌ ๋†์žฅ struct๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

์†Œ์—๊ฒŒ ๋จน์ด๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„ 

 

1. ์•ŒํŒ”ํŒŒ(๊ฑด์ดˆ์˜ ์›์žฌ๋ฃŒ)๋ฅผ ๊ธฐ๋ฅธ๋‹ค.

2. ์•ŒํŒ”ํŒŒ๋ฅผ ์ˆ˜ํ™•ํ•˜์—ฌ ๊ฑด์ดˆ๋ฅผ ๋งŒ๋“ ๋‹ค.

3. ๊ฑด์ดˆ๋ฅผ ์†Œ์—๊ฒŒ ๋จน์ธ๋‹ค.

 

struct Farm {
    func feed(_ animal: Cow) {
        let alfalfa = Hay.grow() // 1
        let hay = alfalfa.harvest() // 2
        animal.eat(hay) // 3
    }
}

 

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ์—ฌ๊ธฐ์„œ ๋™๋ฌผ์ด ์†Œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ง์ด๋‚˜ ๋‹ญ์ด ์ถ”๊ฐ€๋œ๋‹ค๋ฉด ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ์š”?

 

struct Horse {
    func eat(_ food: Carrot) {}
}
struct Chicken {
    func eat(_ food: Grain) {}
}

 

์ถ”๊ฐ€๋œ ๋™๋ฌผ์˜ ์ˆ˜๋งŒํผ ๋†์žฅ์—” ๋จน์ด ์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€๋กœ ์ž‘์„ฑํ•˜์—ฌ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

struct Farm {
	//์†Œ ๋จน์ด
    func feed(_ animal: Cow) {
        let alfalfa = Hay.grow()
        let hay = alfalfa.harvest()
        animal.eat(hay)
    }
    
    //๋ง ๋จน์ด
    func feed(_ animal: Horse) {
        let root = Carrot.grow()
        let carrot = root.harvest()
        animal.eat(carrot)
    }
    
    //๋‹ญ ๋จน์ด
    func feed(_ animal: Chicken) {
        let wheat = Grain.grow()
        let grain = wheat.harvest()
        animal.eat(grain)
    }
}


farm.feed(Cow())
farm.feed(Horse())
farm.feed(Chicken())

 

 

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ๋™๋ฌผ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ถ”๊ฐ€ํ• ์ˆ˜๋ก ๊ฑฐ์˜ ๋น„์Šทํ•œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค.


Identify common capabilities

 

์œ„ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ struct์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŠน์ง•์„ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค.

 

๋™๋ฌผ๋“ค์ด ๊ณตํ†ต์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŠน์ง•์€ ํŠน์ • ๋จน์ด๋ฅผ ๋จน๋Š” ๊ฒƒ์ด์ฃ ?

 

๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋™๋ฌผ์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด eat ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์ถ”์ƒํ™”ํ•˜์—ฌ ๋™๋ฌผ๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ์ ์šฉํ•˜๋ฉด ๋  ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

class Animal {
    func eat(_ food:???) { fatalError("Subclass must implement 'eat'")}
}

Polymorphism

 

์ด๋ ‡๊ฒŒ ํ•œ ์ฝ”๋“œ๋กœ ์—ฌ๋Ÿฌ ํ–‰๋™์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ "Polymorphism" ์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š”๋ฐ์š”. 

 

ํด๋ฆฌ ๋ชฐํ”ผ์ฆ˜์€ ์„ธ ๊ฐ€์ง€ ํ˜•ํƒœ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ์š”.

 

1. ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ํ†ตํ•œ ad-hoc polymorphism

2. ์„œ๋ธŒํƒ€์ž…์„ ์ด์šฉํ•œ subtype polymorphism

3. ์ œ๋„ˆ๋ฆญ์„ ์ด์šฉํ•œ parametric polymorphism

 

 

๊ฐ€์žฅ ๋จผ์ € ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์œ„์—์„œ ๋งŒ๋“ค์–ด ์ค€ ๋™๋ฌผ struct๋“ค์„ ํด๋ž˜์Šค๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ  Animal ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ ๋ฉ”์„œ๋“œ๋ฅผ override ํ•ด์ค๋‹ˆ๋‹ค.

 

class Cow: Animal {
    override func eat(_ food:Hay) {}
}

Using Any

 

ํ•˜์ง€๋งŒ ์œ„์—์„œ ๋งŒ๋“ค์–ด์ค€ Animal ํด๋ž˜์Šค์˜ food ํƒ€์ž…์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ •ํ•  ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

 

๊ณ ๋กœ ๊ทธ๋‚˜๋งˆ ๊ดœ์ฐฎ์€ ๋ฐฉ๋ฒ•์€ food๋ฅผ Any ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

class Animal {
    func eat(_ food:Any) { fatalError("Subclass must implement 'eat'")}
}
class Chicken: Animal {
    override func eat(_ food: Any) {
        guard let food = food as? Grain else { fatalError("Chicken cannot eat \(food)")}
    }
}

 

ํ•˜์ง€๋งŒ ์ด ๋˜ํ•œ ํƒ€์ž…์ด ๋งž์ง€ ์•Š๋Š” ์Œ์‹์ด ๋“ค์–ด์™”์„ ๊ฒฝ์šฐ ์˜ค๋กœ์ง€ ๋Ÿฐํƒ€์ž„์—๋งŒ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ๊ฒฌ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Using type parameter

 

์œ„ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„  Any๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์Šˆํผ ํด๋ž˜์Šค์ธ Animal์—์„œ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„ ๋จน์ด์˜ ํƒ€์ž…์„ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด Animal์— Food๋ฅผ ํƒ€์ž…์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ฒŒ ํ•˜๊ณ , ์ƒ์†๋ฐ›์€ ํ•˜์œ„ ํด๋ž˜์Šค์—” ํŠน์ • ๋จน์ด ํƒ€์ž…์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ž…๋ ฅํ•ด ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๊ฐ–๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด์ฃ .

 

class Animal<Food> {
    func eat(_ food:Food) { fatalError("Subclass must implement 'eat'")}
}
class Chicken: Animal<Grain> {
    override func eat(_ food: Grain) {}
}

 

์ด๋ ‡๊ฒŒ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•ด ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋จน์ด๋ฅผ ๋จน๋Š” ํ–‰๋™์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ๋Š” ํ•ด๋‹น ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ถ”๊ฐ€๋กœ ์ž‘์„ฑํ•ด ์ค˜์•ผํ•œ๋‹ค๋Š” ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋™๋ฌผ์ด ๋จน๋Š” ์Œ์‹ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์‚ฌ๋Š” ๊ณณ, ์–ด๋–ค ๋ฌผํ’ˆ์„ ๋งŒ๋“ค์–ด ๋‚ด๋Š”์ง€ ๋“ฑ์„ ์ถ”๊ฐ€์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด

 

class Animal<Food, Habitat, Commodity> {
    func eat(_ food:Food) { fatalError("Subclass must implement 'eat'")}
}

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋™๋ฌผ๋งˆ๋‹ค ํ•„์š”ํ•œ ํƒ€์ž…์ด <> ์•ˆ์— ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

class Cow: Animal<Hay, Barn, Milk> {
    override func eat(_ food:Hay) {}
}

Build an interface

 

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„ ๋ฌธ์ œ๋“ค์„ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

๋ฐ”๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด์™€ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ, ์ฆ‰ Protocol์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด Feed๋ผ๋Š” ์ž„์˜์˜ ํƒ€์ž…์„ ์ •ํ•ด๋†“๊ณ  eat ๋ฉ”์„œ๋“œ์—” ์ž„์˜์˜ ํƒ€์ž…์„ ์ง€์ •ํ•ด ์ค๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์ด๋“  ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ .

 

protocol Animal {
    associatedtype Feed: FeedType
    func eat(_ food: Feed)
}

 

๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด Class๋กœ ๋˜์–ด ์žˆ๋Š” ๋™๋ฌผ ํด๋ž˜์Šค๋“ค์„ ๋‹ค์‹œ struct๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋ฉ”์„œ๋“œ์— override๋ฅผ ์ œ๊ฑฐํ•ด ์ค๋‹ˆ๋‹ค.

(ํ”„๋กœํ† ์ฝœ์€ enum,struct,actor ๋“ฑ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.)

 

struct Horse: Animal {
    func eat(_ food: Carrot) {}
}

Write generic code

 

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ๋ถ€ํ„ฐ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ œ๋„ˆ๋ฆญํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ฐ€์žฅ ๋ฌธ์ œ๊ฐ€ ๋๋˜ Farm์˜ feed ์ฝ”๋“œ๋ฅผ ์–ด๋– ํ•œ ๋จน์ด๊ฐ€ ์™€๋„ ํ•œ ์ฝ”๋“œ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”๋ฐ์š”.

 

์•„๋ž˜์™€ ๊ฐ™์ด animal์— Animal ํ”„ํ† ํ† ์ฝœ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์œผ๋ฉด ๋ ๊นŒ์š”?

 

struct Farm {
    func feed(_ animal: Animal){...}
}

 

ํ”„๋กœํ† ์ฝœ๊ณผ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์ด ์•„๋‹Œ ๊ฒฝ์šฐ ๋ถˆํˆฌ๋ช…ํ•œ ํƒ€์ž…(Opaque Type) ์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ์š”.

 

๋ถˆํˆฌ๋ช…ํ•œ ํƒ€์ž…์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ฑฐ๋‚˜, ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

 

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ์š”?

 

where

 

์šฐ์„  ์ฒซ ๋ฒˆ์งธ๋กœ๋Š” where ์ ˆ์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด A๋ผ๋Š” ์ž„์˜ ํƒ€์ž… ์ด๋ฆ„์„ ์ •ํ•ด์ฃผ๊ณ  A๋Š” Animal์ด์•ผ ๋ผ๋Š” ๊ฒƒ์„ ์ง€์ •ํ•ด ์ค˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ Animal ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋Š” ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ .

 

struct Farm {
    func feed<A>(_ animal: A) where A:Animal{}
}

 

ํ•˜์ง€๋งŒ where์ ˆ์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹ค์ œ๋ณด๋‹ค ๋” ๋ณต์žกํ•ด ๋ณด์ด๋Š” ๋‹จ์ ์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

 

some

 

์ด๋Ÿฌํ•œ where์ ˆ์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜์—ฌ ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ "some" ์ž…๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋ฉด Animal ํ”„๋กœํ† ์ฝœ์„ ์ค€์ˆ˜ํ•˜๋Š” ํŠน์ • ํƒ€์ž…์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

struct Farm {
    func feed(_ animal: some Animal) {}
}

 

์ด๊ฒƒ์€ SwiftUI๋ฅผ ๊ฒฝํ—˜ํ•ด ๋ณด์‹  ๋ถ„๋“ค์€ ์•„๋ž˜์ฒ˜๋Ÿผ some View๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งŽ์ด ๋ณด์…จ์„ ๊ฑฐ์—์š”.

 

์ด ์˜๋ฏธ๋Š” ๋ฐ”๋กœ View๋ผ๋Š” ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋Š” ํŠน์ •ํƒ€์ž…์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด์ฃ .

 

 

some์„ ์ด์šฉํ•ด์„œ feed ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์–ด๋–ค ๋™๋ฌผ์ด ์ถ”๊ฐ€๋˜๋“  ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ๋กœ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

struct Farm {
    func feed(_ animal: some Animal) {
        let crop = type(of: animal).FeedType.grow()
        let produce = crop.harvest()
        animal.eat(produce)
    }
}

 

์œ„ ๋ฉ”์„œ๋“œ๋ฅผ ์ข€ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค๋ช…ํ•˜๋ฉด ๋จผ์ € crop์€ animal์˜ ํŠน์ • ํƒ€์ž…์„ ์•Œ์•„๋‚ธ ๋’ค ํ•ด๋‹น Feed์— grow ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด Crop ์ธ์Šคํ„ด์Šค๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ ํ•ด๋‹น crop์„ ์ด์šฉํ•˜์—ฌ harvest ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ด ๋จน์ด๋ฅผ ํ• ๋‹นํ•œ ๋’ค animal์˜ eat๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ํ• ๋‹นํ•ด ๋จน์ด๋ฅผ ์ฃผ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

(Feed๋Š” ์ง์ ‘์ ์ธ ๋จน์ด ์ฆ‰ Hay, Grain, Carrot์„ ์˜๋ฏธํ•˜๋ฉฐ Crop์€ ๊ทธ๊ฒƒ์˜ ์›์žฌ๋ฃŒ๊ฐ€ ๋˜๋Š” Alfalfa, Wheat, Root๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๊ฑด ์•„๋ž˜ ๊นƒํ—™ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”!)

 

์•„๋ž˜ ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•ด ์ž์„ธํ•œ ์„ค๋ช…์€ ์—ฌ๊ธฐ ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

protocol AnimalFeed {
    associatedtype CropType: Crop
        where CropType.FeedType == Self
    static func grow() -> CropType
}
protocol Crop {
    associatedtype FeedType: AnimalFeed
        where FeedType.CropType == Self
    func harvest() -> FeedType
}

 

any

 

๋งŒ์•ฝ ์—ฌ๋Ÿฌ ๋™๋ฌผ์—๊ฒŒ ๋จน์ด๋ฅผ ์ฃผ๋ ค๋ฉด ์–ด๋–ค ์‹์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ์š”?

 

๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์€ ์•„๋ž˜์™€ ๊ฐ™์„ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

    func feedAll(_ animals: [Animal]) {
        for animal in animals {
            feed(animal)
        }
    }

 

ํ•˜์ง€๋งŒ ์œ„์—์„œ ํ”„๋กœํ† ์ฝœ์€ ํƒ€์ž…์œผ๋กœ ์ง์ ‘ ํ• ๋‹นํ•˜์ง€ ๋ชปํ–ˆ์ฃ ?

 

์–ด๋–ค ๋™๋ฌผ์ด ๋“ค์–ด์˜ฌ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด some Animal๋กœ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ์š”?

 

some์€ ๊ธฐ๋ณธ ์œ ํ˜•์ด ๊ณ ์ •๋˜๊ณ  ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์š”์†Œ๊ฐ€ ๋™์ผํ•œ ์œ ํ˜•์„ ๊ฐ€์ ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋™๋ฌผ์„ ํ•œ๊บผ๋ฒˆ์— ๊ฐ€์งˆ ์ˆœ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

    func feedAll(_ animals: [some Animal]) {
        for animal in animals {
            feed(animal)
        }
    }โ€‹

 

์ด๋Ÿฌํ•œ ๊ฒƒ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ "any"๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

 

ํ”„๋กœํ† ์ฝœ ์•ž์— any ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด ๋™์ ์œผ๋กœ ํƒ€์ž…์„ ์ €์žฅํ•˜๊ณ  ๋Ÿฐํƒ€์ž„ ์‹œ์— ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ์œ ํ˜•์„ ๋ฐฐ์—ด์— ๋‹ด์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

    func feedAll(_ animals: [any Animal]) {
        for animal in animals {
            feed(animal)
        }
    }

 

์‚ฌ์šฉํ•  ๋•Œ๋„ ์•„๋ž˜์™€ ๊ฐ™์ด any์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋กœํ† ์ฝœ์˜ ์œ ํ˜• ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐฐ์—ด์— ๋‹ด์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

        let farm = Farm()
        let animals:[any Animal] = [Horse(),Chicken(),Cow()]
        farm.feedAll(animals)

Source Code

 

 

GitHub - fomagran/WWDC: Repository to study content published by WWDC

Repository to study content published by WWDC. Contribute to fomagran/WWDC development by creating an account on GitHub.

github.com


Reference

 

 

Embrace Swift generics - WWDC22 - Videos - Apple Developer

Generics are a fundamental tool for writing abstract code in Swift. Learn how you can identify opportunities for abstraction as your code...

developer.apple.com

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€