Swift 在协议上的可比性

时间:2020-12-31 18:49:18

标签: swift protocols comparable

大家新年快乐

protocol Birthday {
    var date: Date { get set }
}
    
class Person: Birthday {
    var date: Date
    var fullName: String

    // ...
}

class Car: Birthday {
    var date: Date
    var color: UIColor

    // ...
}

我希望这符合Comparable,所以我可以做到

Person() > Car()

代替

Person().date > Car().date

我该怎么做?非常感谢

2 个答案:

答案 0 :(得分:2)

您可以轻松完成 >。只需编写以下顶级函数:

func > (lhs: Birthday, rhs: Birthday) -> Bool { lhs.date > rhs.date }

但是您不能将生日与 Comparable 相匹配。 Comparable 要求类型实现以下内容:

static func < (lhs: Self, rhs: Self) -> Bool

Self 是符合协议的类型。协议不符合自身。它们不是“类型”。它们描述类型。 (在某些情况下,可能会生成隐式存在类型,但不能在 Swift 中操作存在类型。)为了具有可比性,类型必须能够将自身与相同类型的另一个事物进行比较,而你无法通过协议获得它。

但是您可以创建协议的任何特定语法。您只需要编写函数即可。

虽然这里有一个技术限制(协议不符合自己),即使 Swift 语法可以支持符合自己的协议(并且将来有办法),你仍然不应该以这种方式实现 Comparable . Comparable 需要 Equatable。一个人永远不能等同于一辆汽车。这是因为 Equatable 需要的不仅仅是 == 函数。它需要可替代性。如果两件事在 Equatable 意义上是“相等的”,那么系统可以总是用一个替换另一个,而你永远不会关心它给了你哪一个。而对于人和汽车来说,情况就不是这样了。

为避免此类问题,不建议在此处使用 <。这意味着这些东西只有一个合理的顺序,而“生日”并不是这些东西的唯一顺序。因此,如果您想比较日期,我绝对建议您直接比较日期。

答案 1 :(得分:0)

感谢@Rob Napier 的精彩回答。

我想添加一些东西 - 对于那些想要符合 Comparable 能够对数组进行排序的人,我写了这个扩展:

extension Array where Element: Birthday {
    mutating func sort() {
        sort(by: { $0.date < $1.date })
    }
    
    func sorted() -> [Element] {
        return sorted(by: { $0.date < $1.date })
    }
}
相关问题