👔CaseReflectable
💾 程式:paiza.io ⬆️ 需要: Mirror, HasMirrors
// --------------------------
//     ⭐ CaseReflectable
// --------------------------
// designed for enums only (use it on other types not recommended)
public protocol CaseReflectable: Loggable {
    /// log enum case (default implementation provided)
    func logEnumCase() -> Self
}
// ⭐ default behavior.
extension CaseReflectable {
    
    /// ⭐ case name
    public var caseName: String {
        let mirror = Mirror(reflecting: self)
        // enum cases:
        // - normal case: no children
        // - case with associated values: one child (with label)
        guard let label = mirror.children.first?.label else {
            return "\(self)"    // normal case
        }
        // ase with associated values
        return label
    }
    
    /// ⭐ associated values
    public var associatedValues: Any? {
        // if no children, a normal case, no associated values.
        guard let firstChild = Mirror(reflecting: self).children.first else {
            return nil
        }
        // return associated values
        return firstChild.value
    }
    
    /// ⭐ log enum case
    @discardableResult
    public func logEnumCase() -> Self {
        if let values = self.associatedValues {
            print("case: .\(caseName), values: \(values), type: \(type(of: values))")
        } else {
            print("case: .\(caseName) (no associated values)")
        }
        return self
    }
}
// -----------------------------
//     ⭐ custom operator ~=
// -----------------------------
/// match enum cases with associated values, while disregarding the values themselves.
/// usage: `Enum.enumCase ~= instance`
public func ~= <Enum: CaseReflectable, AssociatedValue>(
    // an enum case (with associated values)
    enumCase: (AssociatedValue) -> Enum,    // enum case as function
    // an instance of Enum
    instance: Enum
) -> Bool 
{
    // if no associated values, `instance` can't be of `enumCase`
    guard let values = instance.associatedValues else { return false }
    // if associated values not of the same type, return false
    guard values is AssociatedValue else { return false }
    // create an instance from `enumCase` (as function)
    let case2 = enumCase(values as! AssociatedValue)
    // if same case name, return true
    return case2.caseName == instance.caseName
}💾 程式:paiza.io ⬆️ 需要: 👔 CaseReflectable
// enum with associated values
enum Rank {
    case number(Int)
    case jack, queen, king
    case ace(suit: Character)
    case range(min: Int, max: Int)
}
// ⭐ enum cases
let cases: [Rank] = [ 
    .jack, 
    // jack
    // Main.Rank.jack
    // no children
    .number(7), 
    // number(7)
    // Main.Rank.number(7)
    // • number: 7 (Int)
    .ace(suit: "♠️"),
    // ace(suit: "♠️")
    // Main.Rank.ace(suit: "♠️")
    // • ace: (suit: "♠️") ((suit: Character))]
    .range(min: 3, max: 8),
    // range(min: 3, max: 8)
    // Main.Rank.range(min: 3, max: 8)
    // • range: (min: 3, max: 8) ((min: Int, max: Int))
]
// 👔 Loggable
cases.forEach { $0.log().reflect().mirror() }
// 👔 CaseReflectable (case name, associated values)
cases.forEach { $0.logEnumCase() }
// case: .jack (no associated values)
// case: .number, values: 7, type: Int
// case: .ace, values: (suit: "♠️"), type: (suit: Character)
// case: .range, values: (min: 3, max: 8), type: (min: Int, max: Int)- enum case pattern - pattern matching 
- operator (~=) - pattern matching 
- Mirror - required struct. 
Last updated
Was this helpful?