Swift 枚举可以被一般地推断和限制吗?

Can Swift enums be inferred and restricted generically?

我找不到语法,但我想做这样的事情:

class MyClass {
    let stringValue: String // filled in later
    let integerValue: Int   // filled in later

    init(stringValue: String) {
        self.stringValue = stringValue
        self.integerValue = stringValue.hashValue
    }

    init(integerValue: Int) {
        self.integerValue = integerValue
        self.stringValue = String(integerValue)
    }
}

extension MyClass {
    //                     This is invalid syntax, but I think you can understand
    //           vvvvvvvvv I'm trying to give back an enum whose type is inferred
    var enumValue<T: enum>: T? {
        get {
            // This is also invalid; I want to check the type of the enum's raw value
            if T is String {
                return T(rawValue: self.stringValue)
            } else if T is Int {
                return T(rawValue: self.integerValue)
            } else {
                return nil
            }
        }
    }
}

用法如下:

enum MyEnum: String {
    case foo
    case bar
}

func baz(_ some: MyClass) {
    if let myEnum: MyEnum = some.enumValue {
        print(myEnum)
    }
}

let some = MyClass(stringValue: "foo")
baz(some) // prints "foo"

这在 Swift 中可行吗?也就是说,要拥有一个类型被限制为枚举并根据用途推断的通用类型字段或函数,然后使用它来实例化一个枚举值?

一个可能的解决方案是一个通用的重载函数:

extension MyClass {
    func enumValue<T: RawRepresentable>() -> T? where T.RawValue == String {
            return T(rawValue: stringValue)
    }
    func enumValue<T: RawRepresentable>() -> T? where T.RawValue == Int {
            return T(rawValue: integerValue)
    }
}

然后称为

func baz(_ some: MyClass) {
    if let myEnum: MyEnum = some.enumValue() {
        print(myEnum)
    }
}

或者,将枚举类型作为参数传递:

extension MyClass {
    func enumValue<T: RawRepresentable>(_ type: T.Type) -> T? where T.RawValue == String {
            return T(rawValue: stringValue)
    }
    func enumValue<T: RawRepresentable>(_ type: T.Type) -> T? where T.RawValue == Int {
            return T(rawValue: integerValue)
    }
}

并这样称呼它

func baz(_ some: MyClass) {
    if let myEnum = some.enumValue(MyEnum.self) {
        print(myEnum)
    }
}