๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ“ ๊ธฐ๋ก/TIL

[TIL] 20231128

ํ”„๋กœํ† ์ฝœ ์ข€ ๋” ์ž˜ ์‚ฌ์šฉํ•˜๊ธฐ

OOP์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๋‹ค๋ณด๋‹ˆ Swift๋ฅผ ํ†ตํ•œ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์—์„œ ํ”„๋กœํ† ์ฝœ์ด ๋งค์šฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  ํ”„๋กœํ† ์ฝœ์„ ์ •๋ง ์ž˜ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๋“ค์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉฐ.. ์š”์ฆ˜ POP์— ๋” ๊ด€์‹ฌ์ด ๋งŽ์•„์ง€๊ณ  ํ”„๋กœํ† ์ฝœ์„ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•ด๋ณด๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šด๋ ..

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

 

PR์€ ๋‚ ๋ ธ์ง€๋งŒ ๊ทผ๋ฐ ๋ญ”๊ฐ€ ๋”๋” ๋ฌถ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•  .. ํ”„๋กœํ† ์ฝœ ๋” ์ž˜ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์• ..

์ด๋Ÿฐ ์ƒ๊ฐ์— ํ”„๋กœํ† ์ฝœ์„ ์ข€ ๋” ์ž˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ฐพ์•„๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค!

ํ•„์š”ํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์„œ์น˜ํ•ด์„œ ์ฐพ์•„๋ณธ ์ •๋ณด + ์˜ˆ์ „์— ํƒœ๋ผ๊ฐ€ protocol extension์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด์„œ ๊ณต์œ ํ•ด์ค€ ์ž๋ฃŒ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์ •๋ฆฌํ•ด๋ณด๊ณ 

๋ฆฌํŒฉํ† ๋ง๊นŒ์ง€ ํ•ด๋ณด๊ฒ ์Œ! (๋•ก์Šคํˆฌ ํƒœ๋ผ)

associatedtype

associatedtype์€ ํ•œ๋งˆ๋””๋กœ ํ”„๋กœํ† ์ฝœ์—์„œ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•! ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

์ œ๋„ค๋ฆญ์ด๋ž€? ํƒ€์ž…์— ์ œํ•œ์„ ๋‘์ง€ ์•Š๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” Swift ๊ธฐ๋Šฅ์œผ๋กœ, ํ•œ ๋งˆ๋””๋กœ ๋ฒ”์šฉ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๊ฒŒ์‹œ๊ธ€ ์ฐธ๊ณ !

 

[Swift] Generic

์•ˆ๋…•ํ•˜์„ธ์š” ์ œ์ธ์ž…๋‹ˆ๋‹ค :) ์˜ˆ์ „์— TIL๋กœ ์ •๋ฆฌํ–ˆ๋˜ Generic์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๋ธ”๋กœ๊ทธ์—๋„ ํฌ์ŠคํŒ…ํ•ด๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„ ์‡ฝ์ƒฅ ํ•ด์™”์Šต๋‹ˆ๋‹ค ใ…Žใ…Ž ์„œ๋ฒ„ ํ†ต์‹  ์‹œ ์ •๋ง ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š” Generic์— ๋Œ€ํ•ด Apple์˜ S

janechoi.tistory.com

 

ํ”„๋กœํ† ์ฝœ์—์„œ ์ œ๋„ค๋ฆญ์„ ์“ธ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒ ํ•˜๋‹ค๊ฐ€ ์ฐพ์•„๋ณธ๊ฑด๋ฐ, Generic์— ๋Œ€ํ•œ ๊ณต์‹๋ฌธ์„œ์— associatedtype์— ๋Œ€ํ•œ ์„ค๋ช…์ด ์žˆ์—ˆ์Œ ใ…‹ใ…Žใ…Ž..

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/#Associated-Types

ํ”„๋กœํ† ์ฝœ์„ ์ •์˜ํ•  ๋•Œ ํ”„๋กœํ† ์ฝœ ์ •์˜์˜ ์ผ๋ถ€๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ ์—ฐ๊ด€๋œ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฐ๊ด€ ํƒ€์ž…์€ ํ”„๋กœํ† ์ฝœ์˜ ์ผ๋ถ€๋กœ ์‚ฌ์šฉ๋˜๋Š” ์œ ํ˜•์— placeholder ์ด๋ฆ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์—ฐ๊ด€ ํƒ€์ž…์— ์‚ฌ์šฉํ•  ์‹ค์ œ ํƒ€์ž…์€ ํ”„๋กœํ† ์ฝœ์ด ์ฑ„ํƒ๋  ๋•Œ๊นŒ์ง€ ์ง€์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. associatedtype ์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ์—ฐ๊ด€ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

protocol Playable {
    associatedtype GameType
    
    func validateUserInput(_ input: String?) throws -> GameType
    func judgeGame(user: GameType, computer: GameType?, turn: PlayerType) -> GameResultType
    func showMessage(_ messageType: GameResultType, _ turn: PlayerType)
    func playGame(_ result: GameResultType) -> GameResultType
}

 

ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฐ€์œ„๋ฐ”์œ„๋ณด ๊ฒŒ์ž„๊ณผ ๋ฌต์ฐŒ๋น  ๊ฒŒ์ž„ ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐ€์ง€ ๊ฒŒ์ž„์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ, 1~3 ์ˆซ์ž๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์œ„(1)๋ฐ”์œ„(2)๋ณด(3)๋ž‘ ๋ฌต(1)์ฐŒ(2)๋น (3) ๊ฒŒ์ž„ ๊ฐ๊ฐ์—์„œ ๋‹ฌ๋ผ์„œ(ํ‚น..๋ฐ›..์•„..) 

 

@frozen
enum RockPaperScissorsType: Int {
    case none = 0
    case scissors = 1
    case rock = 2
    case paper = 3
    
    func getAdvancedType() -> RockPaperScissorsType {
        switch self {
        case .none:
            return .none
        case .scissors:
            return .rock
        case .rock:
            return .scissors
        case .paper:
            return .paper
        }
    }
}

 

์ด๋ ‡๊ฒŒ ๋ฌต์ฐŒ๋น  ๊ฒŒ์ž„์—์„œ์˜ ์ˆซ์ž๋ฅผ ๊ฐ€์œ„๋ฐ”์œ„๋ณด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ด์คฌ์—ˆ์Œ.. (๊ฐ™์€ enum ํƒ€์ž…์„ ์จ์ฃผ๋ ค๊ณ )

๊ทผ๋ฐ associatedtype์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํƒ€์ž… ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋„ ํ•„์š” ์—†๊ณ , ๋” ์ง๊ด€์ ์ธ ์ฝ”๋“œ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™์Œ!! (enum์€ ํ•˜๋‚˜ ๋” ์ •์˜ํ•ด์ฃผ์–ด์•ผ ํ•˜๊ฒ ์ง€๋งŒ)

protocol extension

ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์  ์ค‘ ํฐ ๋ถ€๋ถ„์„ ์ฐจ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์‚ฌ์‹ค ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ! ์ผ ๊ฒƒ ๊ฐ™์€๋ฐ,

์—ฌ๋Ÿฌ ํด๋ž˜์Šค(or ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•)์—์„œ ํŠน์ • ๋ฉ”์„œ๋“œ๋ฅผ ๋™์ผํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Œ

๊ตฌํ˜„๋ถ€๊นŒ์ง€ ๋˜‘๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ๋ชจ๋“  ํด๋ž˜์Šค(or ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•)๋งˆ๋‹ค ๊ณตํ†ต๋œ ๊ธฐ๋Šฅ์„ ๋‹ค ๊ตฌํ˜„ํ•ด์ค˜์•ผ ํ• ๊นŒ? No...

protocol extension์„ ํ™œ์šฉํ•˜๋ฉด ํ”„๋กœํ† ์ฝœ์—์„œ๋„ ๊ธฐ๋ณธ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค!!!

์ •๋ฆฌ: ํ”„๋กœํ† ์ฝœ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌํ˜„์„ ์ œ๊ณตํ•ด์ฃผ๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ, extension์„ ํ†ตํ•ด์„œ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ

์ƒ์† vs. protocol extension

๋˜‘๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์—ฌ๋Ÿฌ ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ํ•˜๋ฉด ์ƒ์†์ด ์ƒ๊ฐ๋‚จ

๊ทธ๋Ÿผ ์ƒ์†์„ ํ™œ์šฉํ•˜๋ฉด ๋˜์ž–์•„?? ๋ผ๋Š” ์˜๋ฌธ์ด ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์–ด๋–ค ๊ฒฝ์šฐ์— ํ”„๋กœํ† ์ฝœ ์ต์Šคํ…์…˜์„ ํ™œ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ???

 

์ƒ์†์˜ ํ•œ๊ณ„

  • ํด๋ž˜์Šค์—์„œ๋งŒ ์ƒ์† ๊ฐ€๋Šฅ
  • ๋‹จ์ผ ์ƒ์†๋งŒ ๊ฐ€๋Šฅ

๊ธฐ์กด์— ์ƒ์†์—์„œ ์ด๋Ÿฌํ•œ ํ•œ๊ณ„๋ฅผ ๋Š๊ผˆ๋‹ค..

๋งŒ์•ฝ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๊ตฌ์กฐ์ฒด๋‚˜ ์—ด๊ฑฐํ˜•์—์„œ ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์‹ถ๋‹ค. ํ˜น์€ ํ•œ ํด๋ž˜์Šค์—์„œ ์—ฌ๋Ÿฌ ํƒ€์ž…์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค.

ํ•  ๋•Œ ํ”„๋กœํ† ์ฝœ ์ต์Šคํ…์…˜์„ ํ™œ์šฉํ•˜๋ฉด ์ข‹์„ ๋“ฏ!!!

์ƒ์†, ํ”„๋กœํ† ์ฝœ ์ต์Šคํ…์…˜์„ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์ž˜ ์„ ํƒํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.

 

// Runable ํ”„๋กœํ† ์ฝœ
protocol Runable {
    func run()
}

extension Runable {
    func run() {
        print("run!!!!!")
    }
}

// Jumpable ํ”„๋กœํ† ์ฝœ
protocol Jumpable {
    func jump()
}

extension Jumpable {
    func jump() {
        print("jump!!!!!")
    }
}

// Frog ํด๋ž˜์Šค์—์„œ ๋‘ ๊ฐœ์˜ ํ”„๋กœํ† ์ฝœ ์ฑ„ํƒ
class Frog: Runable, Jumpable { }

let frog = Frog()
frog.run()
frog.jump()

 

์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด protocol extension ์•ˆ์—์„œ ํ”„๋กœํ† ์ฝœ์— ์ •์˜ํ•ด๋‘” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ํด๋ž˜์Šค์—์„œ๋Š” ์ฑ„ํƒํ•œ ํ”„๋กœํ† ์ฝœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค์‹œ ๊ตฌํ˜„ํ•  ํ•„์š”์—†์ด ํ˜ธ์ถœํ•ด์„œ ๋ฐ”๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

class Frog: Runable, Jumpable {
    
    func run() {
        print("์šฐ๋‹ค๋‹ค๋‹ค๋‹ค๋‹คใ…")
    }
}

let frog = Frog()
frog.run()
frog.jump()

 

๋งŒ์•ฝ, ํด๋ž˜์Šค ๋‚ด์—์„œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค๋ฉด extension์— ๊ตฌํ˜„๋œ ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” ๋ฉ”์„œ๋“œ ๋ณด๋‹ค, ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ฉ”์„œ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ ๊ตฌํ˜„ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์žฌ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค!!

 

์žฌ์ •์˜ํ•œ run์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

 

ํŠน์ • ํด๋ž˜์Šค์—์„œ๋งŒ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ํ•˜๋„๋ก ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด extension์„ ํ™œ์šฉํ•œ ๊ธฐ๋ณธ ๊ตฌํ˜„ + ์žฌ์ •์˜๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ข‹๊ฒ ๋‹ค!

where clause

where์„ ํ†ตํ•ด์„œ ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์— ์ œํ•œ์„ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.

extension Presentable where Self: UIView {
    
    func show(withMovement: CGFloat, withDuration: CGFloat) {
        self.snp.updateConstraints {
            $0.bottom.equalToSuperview().inset(withMovement)
        }

        guard let superview else { fatalError("Has not superview") }
        UIView.animate(withDuration: withDuration, animations: superview.layoutIfNeeded)
    }
}

 

์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด UIView ์— ๋Œ€ํ•ด์„œ๋งŒ show() ๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ฒ ๋‹ค !! ์ด๋ ‡๊ฒŒ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

๋งŒ์•ฝ UIView ํƒ€์ž…์ด ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ ํ”„๋กœํ† ์ฝœ ์ฑ„ํƒ ํ›„ show๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•˜๋ฉด show() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ผ!! ๋ผ๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋œจ๊ฒŒ ๋จ

 

๋‚˜๋„ ํ”„๋กœํ† ์ฝœ ์ž˜ ์“ฐ๊ณ  ์‹ถ๋‹น...ใ…Ž

'๐Ÿ“ ๊ธฐ๋ก > TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[TIL] 20231130  (2) 2023.11.30
[TIL] 20231129  (1) 2023.11.29
[TIL] 20231124  (1) 2023.11.25
[TIL] 20231123  (1) 2023.11.23
[TIL] 20231122  (0) 2023.11.22