如何将 Swift 字典公开为键值对的类型化序列?
How do I expose a Swift Dictionary as a typed sequence of key-value pairs?
假设我有一个 class 的行:
class Foo<K, V> {
var dict: [K:V] = [:]
}
我想让调用者遍历字典中的键值对,而不提供对字典本身的直接访问。所以调用者可以这样写:
val foo: Foo<Bar, Qux> = ...
for (b, q) in foo.asSequence() {
...
}
现在,由于 Dictionary
符合来自其他语言的 SequenceType
,我希望只需按照以下行向 Foo 添加一个方法:
func asSequence() -> SequenceType<K, V> {
return dict
}
但是,Swift 协议不采用通用参数,SequenceType
是 "can only be used as a generic constraint because it has Self or associated type requirements".
中令人讨厌的类型之一
我可能想出如何将 dict
包装在符合 SequenceType
的东西中(或使 Foo
本身符合 SequenceType
),但我不知道想开始摆弄发电机什么的,直到我绝对必须这样做——如果我只是更好地理解可用选项,这似乎应该是一个单行。 (我不清楚这是否足以让泛型发挥作用,使 (b, q)
具有正确的类型。)
可能有人想出了一个更优雅的解决方案,但这行得通:
class Foo<K : Hashable, V> {
var dict: [K:V] = [:]
func asSequence() -> SequenceOf<(K, V)> {
return SequenceOf(dict)
}
}
... I could probably figure out how to wrap dict in something that conforms to SequenceType ...
这正是 SequenceOf<>
为您所做的。来自其 API
文档:
/// A type-erased sequence.
///
/// Forwards operations to an arbitrary underlying sequence with the
/// same `Element` type, hiding the specifics of the underlying
/// sequence type.
@MartinR 的解决方案很好,但我会更进一步——如果你有一个类型,并且你想给它一个方法 asSequence
,那么听起来你真的想要你的类型符合 SequenceType
本身,这很容易做到:
extension Foo: SequenceType {
func generate() -> GeneratorOf<(K, V)> {
return GeneratorOf(dict.generate())
}
}
当然,如果您的 class 实际上公开了多个内容,这就没有意义了,但如果这个特定序列是其存在的基础,那么这可能是最好的选择。
假设我有一个 class 的行:
class Foo<K, V> {
var dict: [K:V] = [:]
}
我想让调用者遍历字典中的键值对,而不提供对字典本身的直接访问。所以调用者可以这样写:
val foo: Foo<Bar, Qux> = ...
for (b, q) in foo.asSequence() {
...
}
现在,由于 Dictionary
符合来自其他语言的 SequenceType
,我希望只需按照以下行向 Foo 添加一个方法:
func asSequence() -> SequenceType<K, V> {
return dict
}
但是,Swift 协议不采用通用参数,SequenceType
是 "can only be used as a generic constraint because it has Self or associated type requirements".
我可能想出如何将 dict
包装在符合 SequenceType
的东西中(或使 Foo
本身符合 SequenceType
),但我不知道想开始摆弄发电机什么的,直到我绝对必须这样做——如果我只是更好地理解可用选项,这似乎应该是一个单行。 (我不清楚这是否足以让泛型发挥作用,使 (b, q)
具有正确的类型。)
可能有人想出了一个更优雅的解决方案,但这行得通:
class Foo<K : Hashable, V> {
var dict: [K:V] = [:]
func asSequence() -> SequenceOf<(K, V)> {
return SequenceOf(dict)
}
}
... I could probably figure out how to wrap dict in something that conforms to SequenceType ...
这正是 SequenceOf<>
为您所做的。来自其 API
文档:
/// A type-erased sequence.
///
/// Forwards operations to an arbitrary underlying sequence with the
/// same `Element` type, hiding the specifics of the underlying
/// sequence type.
@MartinR 的解决方案很好,但我会更进一步——如果你有一个类型,并且你想给它一个方法 asSequence
,那么听起来你真的想要你的类型符合 SequenceType
本身,这很容易做到:
extension Foo: SequenceType {
func generate() -> GeneratorOf<(K, V)> {
return GeneratorOf(dict.generate())
}
}
当然,如果您的 class 实际上公开了多个内容,这就没有意义了,但如果这个特定序列是其存在的基础,那么这可能是最好的选择。