Как составить протокол, описывающий строково-представимые перечисления?

У меня есть метод, который вызывает метод некоторого менеджера, чтобы сохранить значение int с некоторым ключом. Мой метод получает int и некоторое значение перечисления EnumKey в качестве ключа, выдавливает rawum-значение EnumKey и передает его менеджеру в виде строки:

set(value: Int, forKey key: EnumKey) {
    SomeManager.saveIntValueWithStringKey(valueToSave: value, keyToSave: key.rawValue)
}

enum EnumKey: String { 
    case One="first key"
    case Two="second key"
}

Я хочу сделать это более общим, позволив моему методу получать каждое перечисление со строковым необработанным значением вместо EnumKey. В реализации метода я заменил тип ключевого параметра из EnumKey на протокол GenericKey и заставил EnumKey соответствовать этому протоколу:

 set(value: Int, forKey key: GenericKey) {
    SomeManager.saveIntValueWithStringKey(valueToSave: value, keyToSave: key.rawValue)
}

protocol GenericKey {
    var rawValue: String { get }
}

enum EnumKey: String, GenericKey { 
    case One="first key"
    case Two="second key"
}

Но это String, GenericKey выглядит некрасиво Я хочу, чтобы каждое представляемое строкой перечисление соответствовало автоматически, не упоминая, что оно соответствует протоколу GenericKey в дополнение к типу RawRepresentable и String raw. Что-то вроде:

protocol GenericKey: RawRepresentable {
    associatedtype RawValue = String
}

но компилятор говорит: "Протокол может использоваться только как общее ограничение, потому что он имеет Self или требования к связанному типу".

Что может быть простым способом объяснить компилятору, что протокол описывает только вещи RawRepresentable с RawValue типа String?

1 ответ

Решение

Вы можете определить функцию как универсальную, и определить универсальный тип как RawRepresentable с RawValue типа String, как это:

class Test {
    func set<T: RawRepresentable>(value: Int, forKey key: T) where T.RawValue == String {
        print("value \(value), key: \(key.rawValue)")
    }
}

enum EnumKey: String {
    case One="first key"
    case Two="second key"
}

let t = Test()
t.set(value: 3, forKey: EnumKey.One) // prints "value 3, key: first key"
Другие вопросы по тегам