根据关联值动态初始化枚举

时间:2019-10-09 19:32:49

标签: swift enums mirror

这是我的枚举:

enum E {
    case a(Int), b(String)
}

枚举的关联值类型是唯一的,并且始终是唯一的。

比方说我有这个变量:

let myInt = 0

我想基于变量E,动态地创建一个myInt的实例。这应该导致:

E.a(0)

但是在“现实世界”中,我不知道我得到了什么财产。我只知道一件事:我可以用它初始化枚举E。我需要根据属性值动态初始化枚举。我目前在属性上有一个巨大的开关来初始化枚举,我不希望那样。

但是我不知道如何完成这项任务。我尝试镜像枚举类型,但是我得到了一个复杂的类型,即使知道类型,我也不知道如何继续进行初始化。

所以我得到了某种类型的属性。我知道某些类型与枚举E中的情况匹配,因为恰好有一种情况下关联值对应于属性类型。我想用属性的值在这种情况下初始化该枚举的实例。

3 个答案:

答案 0 :(得分:1)

您可以使用自定义的初始值设定项:(我使用了更具描述性的名称)

enum TypeFinder {
    case int(Int)
    case string(String)
    case unknown(Any)

    init(value: Any) {
        switch value {
        case let v as Int: self = .int(v)
        case let v as String: self = .string(v)
        default: self = .unknown(value)
        }
    }
}

测试:

var unknownTypeValue: Any = "Testing.."

print(TypeFinder(value: unknownTypeValue))

unknownTypeValue = 1234

print(TypeFinder(value: unknownTypeValue))

unknownTypeValue = true

print(TypeFinder(value: unknownTypeValue))

答案 1 :(得分:1)

如果您唯一的起点是最终将成为关联值的类型,则可以使用switch语句:

enum E {
    case a(Int)
    case b(String)

    init(associatedValue: Any) {
        switch associatedValue {
        case is Int:
            self = .a(associatedValue as! Int)
        case is String:
            self = .b(associatedValue as! String)
        default:
            fatalError("Unrecognized type!")
        }
    }
}

let response = E(associatedValue: 1) // .a(1)
let other = E(associatedValue: "haha!") // .b("haha!")

这里的问题是此开关必须是详尽无遗的,这意味着必须覆盖所有所有类型。因此,您要么需要一个垃圾堆(.unreachable(Any)),要么需要一个fatalError,以便可以在开发中抓住它们。

答案 2 :(得分:0)

我相信你可以做这样的事情

enum E: ExpressibleByStringLiteral, ExpressibleByIntegerLiteral {
    
    case a(Int), b(String)
    
    init(stringLiteral value: StringLiteralType) {
        self = .b(value)
    }
    
    init(integerLiteral value: IntegerLiteralType) {
        self = .a(value)
    }
}