swift - Swift 中带有基于字符串的枚举的下标字典

标签 swift generics dictionary enums swift-extensions

我想用 String 键(JSON 字典)扩展 Dictionary 以允许使用任何具有 RawValue< 的 enum 进行下标 类型的 String。最终目标将是多个可用于下标 JSON 字典的枚举

enum JSONKey: String {
    case one, two, three
}

enum OtherJSONKey: String {
    case a, b, c
}

if let one = jsonDictionary[.one] { /* ... */ }
if let b = jsonDictionary[.b] { /* ... */ }

但我不知道如何实现它。我知道我需要扩展 Dictionary,但无法弄清楚通用扩展约束或方法扩展约束。

我的第一个想法是尝试为下标方法添加一个泛型约束。不过,我认为下标方法不允许使用泛型。

extension Dictionary {
    subscript<T: RawRepresentable>(key: T) -> Value? { /* ... */ }
}

即使对下标设置通用约束有效,我仍然需要一种方法来嵌套我的通用约束。或者将字典限制为基于字符串的枚举的键。要将其放入无效的代码中,我想这样做:

extension Dictionary where Key: RawRepresentable where RawValue == String {
    subscript(key: Key) -> Value { /* ... */ }
}

// or

extension Dictionary {
    subscript<T: RawRepresentable where RawValue == String>(key: T) -> Value { /* ... */ }
}

扩展 Dictionary 以接受基于字符串的枚举作为下标是否真的可行?

我关于如何实现类似这样的东西的其他想法包括 enum 继承和为我想用作下标的特定 enums 创建协议(protocol)。我知道其中一些无法完成,但认为值得一提的想法。因此,再次将其放入无效代码中:

enum JSONKey: String {}
enum NumbersJSONKey: JSONKey {
    case one, two, three
}
enum LettersJSONKey: JSONKey {
    case a, b, c
}

// or

protocol JSONKeys {}
enum NumbersJSONKey: JSONKey {
    case one, two, three
}
enum LettersJSONKey: JSONKey {
    case a, b, c
}

// then subscript with
if let one = json[.one] { /* ... */ }

更新:

我已经玩了更多,并且离得更近了一点。下面的扩展可以编译,但如果我真的尝试使用它,它会给我一个“下标不明确”的错误。

extension Collection where Iterator.Element == (key: String, value: AnyObject) {

    // Compiles but can't be used because of ambiguous subscript.
    subscript(key: CustomStringConvertible) -> AnyObject? {
        guard let i = index(where: { $0.key == key.description }) else { return nil }
        return self[i].value
    }

}

@titaniumdecoy 的答案有效,因此它将成为公认的答案,除非有人能想出更好的答案。

最佳答案

Swift 4 支持 Generic Subscripts你现在可以这样做:

extension Dictionary where Key: ExpressibleByStringLiteral {
    subscript<Index: RawRepresentable>(index: Index) -> Value? where Index.RawValue == String {
        get {
            return self[index.rawValue as! Key]
        }

        set {
            self[index.rawValue as! Key] = newValue
        }
    }
} 

它允许您使用 任何 具有字符串的枚举,因为它是 RawValue 类型:

让 value = jsonDict[JSONKey.one]

这现在适用于任何字符串枚举,而不仅仅是 JSONKey

关于swift - Swift 中带有基于字符串的枚举的下标字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38774772/

相关文章:

swift - 在 Xcode 6.0 模式中创建环境变量并从 swift 中的代码中获取它们

swift - getBoundingBox Size 有时会崩溃

Java泛型,列表列表

java - 如何满足kotlin中Class<T>的嵌套泛型要求

c++ - 在 map vector 中查找对

ios - 如何将 safeAreaInsets 集成到当前约束扩展

ios - UIScrollView 不滚动 Swift 3

java - 我怎样才能用 Java 泛型解决这个问题?

ios - 在 Swift 3 中对成员 'subscript' 的引用不明确

python - python 映射中的派生值