Stuart Breckenridge

Some Answers to the Question on Nested Enums

A few days ago I asked if it was possible to write a function using the outermost enum to reference the nested enums. The example code:

enum ArmyRanks {
    enum Commissioned {
        case SecondLieutenant, Lieutenant, Captain
    }
    
    enum NonCommissioned {
        case Private, LanceCorporal, Corporal
    }
}

// Desired outcome:

struct Soldier {
    let rank:ArmyRanks
}

let s = Soldier(rank: .Commissioned.Captain) 

Solution 1

Separate the outermost enum, make it a protocol, and make the nested enums conform to the protocol:

protocol ArmyRanks {}

enum Commissioned:ArmyRanks {
        case SecondLieutenant, Lieutenant, Captain
    }
    
enum NonCommissioned:ArmyRanks {
        case Private, LanceCorporal, Corporal
    }
    
struct Soldier {
    let rank: ArmyRanks
}

let s = Soldier(rank: Commissioned.Captain)

switch soldier.rank
{
    case is Commissioned:
        print("Is a commissioned officer: \(soldier.rank)")
    case is NonCommissioned:
        print("Is a non-commissioned officer: \(soldier.rank)")
    default:
        break
}

Solution 2

Add cases with associated values to the outermost enum:

enum Ranks{
    case Commissioned(CommissionedRanks)
    case NonCommissioned(NonCommissionedRanks)
    
    enum CommissionedRanks {
        case SecondLieutentant, Lieutentant, Captain
    }
    
    enum NonCommissionedRanks {
        case Private, LanceCorporal, Corporal
    }
}

struct Soldier {
    let rank:Ranks
}

let soldier = Soldier(rank: .Commissioned(.Captain))

switch soldier.rank
{
case .Commissioned(let description):
		print("Commissioned Officer: \(description)") // prints "Commissioned Officer: Captain"
case .NonCommissioned(let description):
		print("Non Commissioned Officer: \(description)")
}

The latter of these two solutions is my preferred approach.

Credit to @ryanbooker on the Swift-Lang Slack channel for proposing both solutions.


— Supported by —