扩展Collection协议实现removingDuplicates时遇Equatable运算符报错疑问
为什么扩展Collection添加removingDuplicates会报Equatable的==错误?
嘿,这个问题我之前也踩过坑,可不是编译器的bug哦,是咱们对泛型协议扩展的约束逻辑理解不到位导致的~
问题根源
Collection协议本身并没有要求它的Element类型遵循Equatable,所以当你直接扩展Collection并尝试用==(或者依赖==的方法比如contains)比较元素时,编译器根本不知道怎么处理——它没法确认当前的Element是否实现了==运算符,自然就会抛出那个看似矛盾的错误。
举个例子,你可能写了类似这样的错误代码:
extension Collection { func removingDuplicates() -> [Element] { var seen: [Element] = [] for element in self { if !seen.contains(element) { // 这里触发报错,因为Element未约束为Equatable seen.append(element) } } return seen } }
正确的解决方式
你需要在扩展Collection的时候,给Element加上Equatable的泛型约束,明确告诉编译器:这个扩展只适用于元素遵循Equatable的集合类型。修改后的代码如下:
extension Collection where Element: Equatable { func removingDuplicates() -> [Element] { var seen: [Element] = [] for element in self { if !seen.contains(element) { seen.append(element) } } return seen } }
额外优化(可选)
如果想让这个方法的性能更好(尤其是对于大型集合),可以用Set来记录已见过的元素,因为Set.contains的时间复杂度是O(1),而数组的contains是O(n):
extension Collection where Element: Hashable { func removingDuplicates() -> [Element] { var seen = Set<Element>() return filter { seen.insert($0).inserted } } }
这里把约束换成了Hashable,因为Set的元素必须是可哈希的,这样效率会更高。
内容的提问来源于stack exchange,提问作者jeremyabannister
相关产品推荐
相关产品推荐

