1. Nested Types πŸ‘©β€πŸ’»

Enumerations λŠ” 주둜 νŠΉμ • Classes λ˜λŠ” Structures 의 κΈ°λŠ₯을 μ§€μ›ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€. μœ μ‚¬ν•˜κ²Œ 더 λ³΅μž‘ν•œ νƒ€μž…μ˜ context μ—μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μˆœμˆ˜ν•˜κ²Œ Utility Classes or Structuresλ₯Ό μ •μ˜ν•˜λŠ” 것이 νŽΈλ¦¬ν•  μˆ˜λ„ μžˆλ‹€.
이λ₯Ό μœ„ν•΄ Swift 의 Classes, Structures, Enumerations λŠ” λͺ¨λ‘ Nested Typesλ₯Ό μ§€μ›ν•œλ‹€. 이λ₯Ό 톡해 scopeλ₯Ό μ œν•œν•  수 μžˆλ‹€. Nested Types λŠ” μ§€μ›ν•˜λŠ” νƒ€μž…μ˜ λ‚΄λΆ€ μ€‘κ΄„ν˜Έ 내에 μž‘μ„±ν•΄μ•Όν•˜λ©°, Nested Types λŠ” ν•„μš”ν•œ 만큼 쀑첩이 κ°€λŠ₯ν•˜λ‹€.

Nested Functions μ—μ„œ 이미 νƒ€μž…μ˜ 쀑첩을 μž‘μ„±ν•΄λ³Έ 적 μžˆλ‹€. Swift λŠ” First-Class Citizens λ₯Ό μ§€μ›ν•˜λŠ” μ–Έμ–΄λ‘œ 이 κΈ€μ—μ„œ μ„€λͺ…ν•˜λ €λŠ” Classes, Structures, Enumerations Types 의 쀑첩은 Function Types 의 쀑첩과 크게 λ‹€λ₯΄μ§€ μ•Šλ‹€.

2. Nested Types in Action πŸ‘©β€πŸ’»

λΈ”λž™μž­ κ²Œμž„μ„ μœ„ν•΄ Structure λ₯Ό μ •μ˜ν•΄λ³΄μž. μΉ΄λ“œμ˜ λͺ¨μ–‘에 따라 μ„ΈνŠΈλ₯Ό λ‚˜λˆ„λŠ” Suit Enumeration, μΉ΄λ“œμ˜ μˆ«μžμ— 따라 등급을 λ‚˜λˆ„λŠ” Rank Enumeration λ₯Ό Nested Types 둜 갖도둝 ν•  수 μžˆλ‹€.

그리고 Rank λŠ” λ‹€μ‹œ β€˜λ°˜λ“œμ‹œ μ €μž₯ν•  κ°’ ν•˜λ‚˜β€™μ™€ β€˜Optional 둜 μ €μž₯ν•  λ‹€λ₯Έ κ°’ ν•˜λ‚˜β€™λ₯Ό ꡬ쑰화 ν•˜κΈ° μœ„ν•΄ Values Structure λ₯Ό Nested Types 둜 κ°–λŠ”λ‹€. 그리고 Rankκ°€ 항상 μ΅œμ‹  value 값을 얻도둝 ν•˜κΈ° μœ„ν•΄ Values Type 의 Computed Property λ₯Ό values λ³€μˆ˜λ₯Ό κ°–λŠ”λ‹€.

이제 이 두 Nested Types λ₯Ό 가지고 BlackjackCard Structure λ₯Ό μ •μ˜ν•œλ‹€. BlackjackCard 은 rank 와 suit λ₯Ό properties 둜 κ°–κ³ , 이것을 μ„€λͺ…ν•˜κΈ° μœ„ν•œ description 을 computed property 둜 κ°–λŠ”λ‹€.

struct BlackjackCard {

    // nested Suit enumeration
    enum Suit: Character {
        case spades = "β™ ", hearts = "β™‘", diamonds = "β™’", clubs = "♣"
    }

    // nested Rank enumeration
    enum Rank: Int {
        case two = 2, three, four, five, six, seven, eight, nine, ten
        case jack, queen, king, ace
        struct Values {
            let first: Int, second: Int?
        }
        var values: Values {
            switch self {
            case .ace:
                return Values(first: 1, second: 11)
            case .jack, .queen, .king:
                return Values(first: 10, second: nil)
            default:
                return Values(first: self.rawValue, second: nil)
            }
        }
    }

    // BlackjackCard properties and methods
    let rank: Rank, suit: Suit
    var description: String {
        var output = "suit is \(suit.rawValue),"
        output += " value is \(rank.values.first)"
        if let second = rank.values.second {
            output += " or \(second)"
        }
        return output
    }
}
let aceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
let kingOfHearts = BlackjackCard(rank: .king, suit: .hearts)
let sixOfDiamonds = BlackjackCard(rank: .six, suit: .diamonds)

print("The ace of spades : \(aceOfSpades.description)")
print("The king of hearts : \(kingOfHearts.description)")
print("The six of diamonds : \(sixOfDiamonds.description)")
The ace of spades : suit is β™ , value is 1 or 11
The king of hearts : suit is β™‘, value is 10
The six of diamonds : suit is β™’, value is 6

3. Referring to Nested Types πŸ‘©β€πŸ’»

Nested TypesλŠ” 기본적으둜 이것이 μ •μ˜λœ context 의 λ‚΄λΆ€λ‘œ λ²”μœ„κ°€ μ œν•œλœλ‹€. μ΄λ ‡κ²Œ μΊ‘μŠν™” ν•¨μœΌλ‘œμ¨ μ „μ—­μ—μ„œ μ ‘κ·Όν•  ν•„μš”κ°€ μ—†λŠ” Types λ₯Ό 숨겨 μ½”λ“œλ₯Ό λ”μš± μ•ˆμ „ν•˜κ³  가독성 λ†’κ²Œ λ§Œλ“€ 수 μžˆλ‹€. ν•˜μ§€λ§Œ Nested Types λŠ” Closures 의 Capturing Values 와 λ‹€λ₯΄κ²Œ μ™„μ „νžˆ κ²©λ¦¬λ˜λŠ” 것은 μ•„λ‹ˆλ‹€.

λ§Œμ•½ 2~3개의 νƒ€μž…μ—μ„œλ§Œ μ‚¬μš©ν•  μ–΄λ–€ Nested Typesκ°€ μžˆλ‹€κ³  ν•΄λ³΄μž. 이λ₯Ό μ „μ—­μœΌλ‘œ λ§Œλ“€λ©΄ 2~3개의 νƒ€μž…μ—μ„œ κ³΅μœ κ°€ κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ 이런 νƒ€μž…μ΄ λ§Žμ•„μ§€λ©΄ μ „μ—­ scope μ˜€μ—Όμ΄ μΌμ–΄λ‚˜ λΆˆν•„μš”ν•˜κ²Œ λ³΅μž‘ν•΄μ§ˆ κ°€λŠ₯성이 λ†’λ‹€. 이λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ 2~3개의 νƒ€μž…λ§ˆλ‹€ λ™μΌν•œ Nested Types λ₯Ό λ§Œλ“€λ©΄ μ „μ—­ scope μ˜€μ—Όμ€ λ˜μ§€ μ•Šκ² μ§€λ§Œ, μ½”λ“œμ˜ 쀑볡이 λ°œμƒν•˜κ³  μœ μ§€λ³΄μˆ˜ μ‹œ μ½”λ“œμ˜ λ³€κ²½ 사항을 놓쳐 Human Errors λ₯Ό λ§Œλ“œλŠ” 원인이 될 수 μžˆλ‹€.

이런 경우 κ°€μž₯ 연관성이 높은 곳에 ν•˜λ‚˜μ˜ Nested Types λ₯Ό μ •μ˜ν•˜κ³ , μ™ΈλΆ€ νƒ€μž…μ—μ„œ μ ‘κ·Όν•  경우 ν•΄λ‹Ή Nested Types κ°€ μ •μ˜λœ κ°€μž₯ μ™ΈλΆ€ Types 에 μ ‘κ·Όν•΄ Hierarchy ꡬ쑰λ₯Ό 타고 λ‚΄λ €κ°€ λͺ…μ‹œμ μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€. μ΄λ ‡κ²Œ λͺ…μ‹œμ μΈ 접근을 ν—ˆμš©ν•¨μœΌλ‘œμ¨ Nested Types λŠ” μ „μ—­ scope 의 μ˜€μ—Όμ„ μ˜ˆλ°©ν•˜λ©° ν•„μš”μ— 따라 λͺ…μ‹œμ  접근을 ν†΅ν•œ μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ„ λ™μ‹œμ— 확보할 수 μžˆλ‹€.

let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
print(heartsSymbol)     // β™‘




Reference

  1. β€œNested Types.” The Swift Programming Language Swift 5.7. accessed Jan. 16, 2023, Swift Docs Chapter 19 - Nested Types.