如何将Swift Dictionary公开为键值对的键入序列?

时间:2015-02-28 21:01:51

标签: swift generics dictionary

说我有一个类:

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是那些令人烦恼的类型之一,而且#34;只能用作通用约束,因为它具有自我或相关的类型要求&#34 ;

我可能想出如何将dict包裹在符合SequenceType(或使Foo本身符合SequenceType)的内容中,但我不知道我想开始搞乱发电机等什么直到我绝对不得不 - 如果我更好地理解可用的选项,这似乎应该是一个单线程。 (并且我不清楚这是否足以使泛型工作,以便(b, q)具有正确的类型,无论如何。)

2 个答案:

答案 0 :(得分:2)

@ MartinR的解决方案很好,但我会更进一步 - 如果你有一个类型,并且你想给它一个方法asSequence,那么听起来你真的希望你的类型符合到SequenceType本身,这很容易做到:

extension Foo: SequenceType {
    func generate() -> GeneratorOf<(K, V)> {
        return GeneratorOf(dict.generate())
    }
}

当然,如果你的班级实际上暴露了多个事情,这是没有意义的,但如果这个特定的序列是其存在的基础,那么这可能是最好的选择。

答案 1 :(得分:1)

可能有人想出一个更优雅的解决方案,但这有效:

class Foo<K : Hashable, V> {
    var dict: [K:V] = [:]

    func asSequence() -> SequenceOf<(K, V)> {
        return SequenceOf(dict)
    }
}
  

...我可能想出如何将dict包装成符合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.