【问题标题】:How do I implement Swift's Comparable protocol?如何实现 Swift 的 Comparable 协议?
【发布时间】:2014-06-20 19:54:23
【问题描述】:

如何在 Swift 中使用 Comparable 协议?在声明中它说我必须实现三个操作 =。我把所有这些都放在课堂上,但它不起作用。我还需要拥有这三个吗?因为应该可以从一个单一的推断出所有这些。

【问题讨论】:

    标签: compare protocols swift


    【解决方案1】:

    Comparable 协议扩展了 Equatable 协议 -> 实现它们两个

    Apple's Reference 是 Apple 的一个示例(在 Comparable 协议参考中),您可以看到应该如何做:不要将操作实现放在类中,而是放在外部/全局范围内。此外,您只需从 Comparable 协议实现 < 运算符,从 Equatable 协议实现 ==

    正确示例:

    class Person : Comparable {
        let name : String
    
        init(name : String) {
            self.name = name
        }
    }
    
    func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.name < rhs.name
    }
    
    func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
    
    let paul = Person(name: "Paul")
    let otherPaul = Person(name: "Paul")
    let ben = Person(name: "Ben")
    
    paul > otherPaul  // false
    paul <= ben       // false
    paul == otherPaul // true
    

    【讨论】:

    • 如何在操场上做到这一点?
    • 当实际代码根本不在类中时,我不明白这是如何被认为是“实现的”......不应该 ==
    • @fjlksahfob 原因是它在类外的范围内向运算符添加了扩展。如果您愿意,您甚至可以执行类似func == (lhs: ClassA, rhs: ClassB) -&gt; Bool 的操作来比较两个不同的类(从测试来看,它似乎只在指定的方向上工作,因此您还必须创建func == (lhs: ClassB, rhs: ClassA) -&gt; Bool)。换句话说,Swift 编译器将(X == Y) 解释为==(X, Y) 而不是X.==(Y)
    • @Kametrixom,哦,酷,我没有用过Haskell,所以我不知道,谢谢你的启发。 C# 确实有自定义运算符重载,但为了排序,您使用 IComparable 接口,并通过执行 a.CompareTo(b)
    • 在 Swift 5 中,我发现在遵循 Comparable 时,我不需要遵循 equatable 或实现 ==。我只实现了&lt;,并且仍然能够测试是否相等。重复使用 &lt; 与交换参数是否只是聪明?
    【解决方案2】:

    这是 Kametrixom 对 Swift 3 的回答的更新:

    class Person : Comparable {
    
        let name : String
    
        init(name : String) {
            self.name = name
        }    
    
        static func < (lhs: Person, rhs: Person) -> Bool {
            return lhs.name < rhs.name
        }
    
        static func == (lhs: Person, rhs: Person) -> Bool {
            return lhs.name == rhs.name
        }
    }
    

    然后可以将Person 类的实例与关系运算符进行比较,如下所示:

    let paul = Person(name: "Paul")
    let otherPaul = Person(name: "Paul")
    let ben = Person(name: "Ben")
    
    print(paul > otherPaul)  // false
    print(paul <= ben)       // false
    print(paul == otherPaul) // true
    

    【讨论】:

      【解决方案3】:

      要实现 Swift 的Comparable 协议,您需要首先通过实现static func == (lhs: Self, rhs: Self) -&gt; Bool 来符合Equatable 协议,然后为Comparable 实现唯一需要的函数static func &lt; (lhs: Self, rhs: Self) -&gt; Bool

      您应该在结构/类本身内实现符合协议的方法,而不是声明全局运算符重载。尽管全局运算符重载满足协议一致性,但以这种方式声明它们而不是结构/类上的预期静态方法是不好的做法。

      如果您查看文档示例,您会看到与示例代码相同。

      我会改为写以下内容:

      class Person: Comparable {
          let name: String
      
          init(name: String) {
              self.name = name
          }
      
          static func < (lhs: Person, rhs: Person) -> Bool {
              return lhs.name < rhs.name
          }
      
          static func == (lhs: Person, rhs: Person) -> Bool {
              return lhs.name == rhs.name
          }
      }
      

      甚至像这样从类声明中分离出协议一致性:

      class Person {
          let name: String
      
          init(name: String) {
              self.name = name
          }
      }
      
      extension Person: Comparable {
          static func < (lhs: Person, rhs: Person) -> Bool {
              return lhs.name < rhs.name
          }
      
          static func == (lhs: Person, rhs: Person) -> Bool {
              return lhs.name == rhs.name
          }
      }
      

      这可能更接近生产级代码。

      【讨论】:

        猜你喜欢
        • 2015-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-14
        相关资源
        最近更新 更多