你能扩展具有特定约束的泛型类(例如数组)吗?

时间:2014-08-08 00:05:40

标签: generics swift

我想扩展Array类,但仅适用于符合SequenceType协议的元素。

我想写的代码/我认为合理的代码是:

extension Array {
    func flatten<T: SequenceType>() -> [T.Generator.Element] {
        var result = [T.Generator.Element]() // *** [2]

        for seq: T in self { // *** [1]
            for elem in seq {
                result += [elem]
            }
        }

        return result
    }
}

然而,Swift似乎创建了T的两个版本。我假设一个来自正常的Array声明,另一个来自对我的方法的尝试约束。

特别是,这意味着第[1]行给出了可爱的错误'T' is not convertible to 'T'

类似地,[2]处的行失败,因为在该上下文中,Swift不会将T识别为具有.Generator成员(尽管声明中的返回类型注释有效)。

我已经尝试了许多其他配方(包括使用,例如T where T: SequenceType),但我似乎找不到表达这种约束的方法。 这是可能的,还是我在错误的树上咆哮?

2 个答案:

答案 0 :(得分:2)

作为你的问题的评论者已经说过,答案是否定的。但是,从Swift标准库的组织中可以清楚地看出,不鼓励将专用泛型函数编写为方法。 (我怀疑随着Swift的类型系统的发展,它会发生变化。)例如,请注意Swift的本机数组类型没有contains方法。 相反,它被实现为全局函数,因为要求元素为Equatable。这正是因为您遇到的限制:无法在方法中专门化封闭类的泛型类型参数,无论它是否为扩展名。 (在我看来,这是一个非常不幸的限制。)

所以,正如斯威夫特目前的立场,我会&#34;实施&#34; flatten只需使用join,例如join([], arrayOfArrays)

答案 1 :(得分:2)

现在可以使用Swift 2:

extension SequenceType where Generator.Element : SequenceType {
    func flatten() -> [Generator.Element.Generator.Element] {
        var result: [Generator.Element.Generator.Element] = []
        for seq in self {
            result += seq
        }
        return result
    }
}

[[1,2,3],[],[2,4,5]].flatten() // [1, 2, 3, 2, 4, 5]

请注意,虽然我们在库中有flatMap,但这个特定功能并不重要。