【问题标题】:Selecting types for an Array extension为数组扩展选择类型
【发布时间】:2021-04-29 20:24:22
【问题描述】:

我正在尝试扩展Array.contains 函数以允许可选参数并在参数为零时返回false。我从这个开始:

extension Array {
    func contains(_ element: Element?) -> Bool {
        if let element = element {
            return self.contains(element)
        } else {
            return false
        }
    }
}

当参数为 nil 时,调用代码会正确找到我的函数版本。但是,此函数中的self.contains 不会调用原始版本——它会调用自身并创建一个无限循环。有没有办法让self.contains 行调用原函数?

接下来,我尝试用不同的实现替换self.contains,但我想不出任何不需要将扩展​​限制为Element: Equatable,就像这样:

extension Array where Element: Equatable {
    func contains(_ element: Element?) -> Bool {
        if let element = element {
            return (self.firstIindex(of: element) != nil)
        } else {
            return false
        }
    }
}

但是,这使得该功能无法用于 UIButton、Dictionary 和其他我需要使用它的元素类型。原始的contains 函数如何为这些类型执行此操作? (我搜索了一下,没找到它的源代码。)

接下来,我删除了约束并更改了方法签名以消除我的扩展函数和原始函数之间的歧义:

extension Array {
    func contains(optional element: Element?) -> Bool {
        if let element = optional {
            return self.contains(element)
        } else {
            return false
        }
    }
}

但是当我更改方法签名时,编译器错误告诉我self.contains 行现在要求 Element 符合 Equatable。 原始函数如何免除此限制,而签名略有不同的函数需要它?

我觉得这应该是微不足道的,但我已经花了几个小时,但找不到有效的设置。有人可以给我一个解决方案吗?

【问题讨论】:

  • "原函数如何不受此限制?"不是……见documentation。注意措辞:“当 Element 符合 Equatable 时可用。”
  • 另请注意:UIButtonDictionary 都符合 Equatable

标签: swift types collections protocols extension-methods


【解决方案1】:

在看到@Sweeper 关于 UIButton 和 Dictionary 是平等的评论后,我再次尝试使用该约束。我之前看到 UIButtons 数组出现错误,但这次没有,所以这些肯定是由其他东西触发的。然而,我认为是字典的错误实际上只是简单的结构。我使用this answer 使我的结构符合 Equatable,现在一切都按预期工作。

实际上,添加了 Equatable 约束后,不再出现无限循环,所以我可以回到我的函数的第一个版本:

extension Array where Element: Equatable {
    func contains(_ element: Element?) -> Bool {
        if let element = element {
            return self.contains(element)
        } else {
            return false
        }
    }
}

显然,contains() 的一个版本没有 Equatable 约束,这是我之前使用结构时调用的,以及我的自定义函数使用 self.contains() 调用的。无论如何,这些都是经验教训:

  1. 创建原生函数的变体时,添加与原始函数相同的类型约束。

  2. 使自定义结构符合 Equatable 以便与集合一起使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-12
    • 2021-10-17
    • 2022-09-24
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    相关资源
    最近更新 更多