【发布时间】:2016-08-04 18:24:25
【问题描述】:
我想用String 键(JSON 字典)扩展Dictionary,以允许使用任何RawValue 类型为String 的enum 进行下标。最终目标将是多个 enums 可用于下标 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 创建一个协议。我知道其中一些无法完成,但认为值得一提的想法。因此,再次将其放入无效的代码中:
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 的答案有效,因此除非有人能想出更好的答案,否则它将是公认的答案。
【问题讨论】:
-
在
[String:String]字典中,您将无法使用.one为其下标。您必须使用JSONKey.one来执行此操作(除了您要询问的扩展名之外)。 -
还是可以的。这允许 JSON 键的命名空间,而不是输入
json["someKey"]或保留一堆String常量。 -
想通了。看看我的回答。
-
虽然我不认为它有助于解决您的问题,但您可以将多个 where 子句与逗号组合:
where Key: RawRepresentable, Key.RawValue == String
标签: swift generics dictionary enums swift-extensions