if-let Any для RawRepresentable<String>

Давайте предположим это:

enum MyEnum: String { case value }
let possibleEnum: Any = MyEnum.value
if let str = stringFromPossibleEnum(possibleEnum: possibleEnum)

Какой мой лучший вариант реализации stringFromPossibleEnum не зная имя типа enum?

func stringFromPossibleEnum(possibleEnum: Any) -> String? {
//    how should this be implemented without knowing enum type name?
}

UPD: хорошо, становится лучше, с этим я могу сказать, если possibleEnum это перечисление:

if Mirror(reflecting: possibleEnum).displayStyle == .enum { print("yes!") }

Но как сказать, если это Stringна основе enum?

UPD: этот твит предполагает, что вы можете получить rawValue как любой из Enum. Вы можете тогда проверить, если это rawValue является String, Но как получить rawValue от Mirror?

3 ответа

Решение

Хорошо, так что это в принципе не выполнимо в настоящее время из коробки, так как вы не можете as?-каст RawRepresentable, а также Mirror не обеспечивает rawValue для перечислений.

Я бы сказал, что лучше всего сделать собственный protocolобеспечить реализацию по умолчанию для String-основан RawRepresentable и согласовать все перечисления вручную следующим образом:

Предполагая, что это перечисления:

enum E1: String { case one }
enum E2: String { case two }
enum E3: String { case three }

StringRawRepresentable реализация протокола и по умолчанию:

protocol StringRawRepresentable {
    var stringRawValue: String { get }
}

extension StringRawRepresentable 
where Self: RawRepresentable, Self.RawValue == String {
    var stringRawValue: String { return rawValue }
}

Соответствуйте всем необходимым существующим перечислениям к протоколу:

extension E1: StringRawRepresentable {}
extension E2: StringRawRepresentable {}
extension E3: StringRawRepresentable {}

И теперь мы можем бросить StringRawRepresentable:

func stringFromPossibleEnum(possibleEnum: Any) -> String? {
    if let e = possibleEnum as? StringRawRepresentable { return e.stringRawValue }
    return nil
}

stringFromPossibleEnum(possibleEnum: E2.two as Any)

Не уверен, что вы действительно пытаетесь достичь здесь, но вот оно:

enum MyEnum: String {
    case A
    case B
    case C
}

func stringFromEnum<T: RawRepresentable>(_ value: T) -> String
    where T.RawValue == String {
    return value.rawValue
}

print(stringFromEnum(MyEnum.A))
print(stringFromEnum(MyEnum.B))
print(stringFromEnum(MyEnum.C))

На основе ответа Дэнни П.

      enum E1: String { case one }
enum E2: String { case two }
enum E3: String { case three }


func stringFromPossibleEnum(possibleEnum: Any) -> String? {
    if let e = possibleEnum as? (any RawRepresentable),
       let str = e.rawValue as? String {
        return str
    }
    return nil
}

stringFromPossibleEnum(possibleEnum: E2.two as Any)
Другие вопросы по тегам