如何使具有泛型属性的结构符合可等式?

Posted

技术标签:

【中文标题】如何使具有泛型属性的结构符合可等式?【英文标题】:How do I conform a struct with a generic property to equatable? 【发布时间】:2021-06-28 15:31:13 【问题描述】:

我有以下结构:

struct IndexAndItem<ItemType> 
    let index: Int
    let item: ItemType

我需要使IndexAndItem&lt;MyClass&gt; 符合Equatable

MyClass 已经符合Equatable 但是当我尝试时:

extension IndexAndItem: Equatable where ItemType == MyClass 
    internal static func == (lhs: IndexAndItem, rhs: IndexAndItem) -> Bool 
        lhs.item == rhs.item
    

我收到一个错误:

方法“==”必须声明为公共,因为它符合公共协议“Equatable”中的要求

将其更改为public 然后会引发另一个错误,要求将public 替换为internal

我在这里做错了什么?

【问题讨论】:

Xcode 12.5。不允许我标记为内部 为什么不简单地struct IndexAndItem&lt;ItemType : Equatable&gt; : Equatable ... 不带扩展名? @vadian 我正在使用扩展,所以一致性只发生在测试目标中 @Kex 你做得不对,你不应该仅仅为了测试目的而增加你的应用程序代码。它可能感觉不那么嘈杂,但您实际上是在向那些偶然发现该单元测试代码的人引入错误的期望,期望生产结构是平等的。请改用辅助方法,或者如果有意义,请将 Equatable 一致性添加到应用代码中。 【参考方案1】:

正如上面 @vadian 建议的那样,您可以这样做 -

struct IndexAndItem<ItemType: Equatable>: Equatable 
    let index: Int
    let itemType: ItemType

这样,您不必担心以后有更多 ItemType 类型与 IndexAndItem 一起使用。


如果您只是想知道如何让它以您尝试的方式工作,以下是我对两种 internal 类型的工作方式。

class MyClass: Equatable 
    let flag: Bool
    init(flag: Bool)  self.flag = flag 
    static func == (lhs: MyClass, rhs: MyClass) -> Bool 
        lhs.flag == rhs.flag
    


struct IndexAndItem<ItemType> 
    let index: Int
    let itemType: ItemType


// Restricted to one type `MyClass`
extension IndexAndItem: Equatable where ItemType == MyClass 


// Open to all types that conform to `Equatable`
extension IndexAndItem: Equatable where ItemType: Equatable 

只要您的ItemType 符合Equatable,编译器就可以为您综合符合性。您不需要实现任何方法。

【讨论】:

Restricted to one type MyClass`。你如何定义static func == (lhs: IndexAndItem, rhs: IndexAndItem) -&gt; Bool?当我使用return lhs.item = rhs.item时,我得到Cannot assign to property: 'item' is a 'let' constant 这种情况下不需要定义static func ==,编译器可以自动合成它的实现。这就是答案的最后一行所说的。

以上是关于如何使具有泛型属性的结构符合可等式?的主要内容,如果未能解决你的问题,请参考以下文章

具有可互换属性的可散列结构?

具有多个结构的泛型和依赖倒置

如何调用具有泛型类型的结构的关联函数?

Swift - 如何使这个结构符合 Codable?

C# 泛型的使用

➽08结构体与类