Swift 在协议上具有可比性
Swift comparable on a protocol
大家新年快乐
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
我该怎么做?非常感谢
您可以>
轻松完成。只需编写以下顶层函数:
func > (lhs: Birthday, rhs: Birthday) -> Bool { lhs.date > rhs.date }
但是你不能让 Birthday 符合 Comparable。 Comparable 要求类型实现以下内容:
static func < (lhs: Self, rhs: Self) -> Bool
Self
是符合协议的类型。协议不符合自身。它们不是“类型”。他们描述类型。 (在某些情况下,可能会生成隐式存在类型,但存在类型不能在 Swift 中进行操作。)要具有可比性,一个类型必须能够将自己与另一个 相同的事物进行比较输入,你无法通过协议获得它。
但是您可以创建任何您希望在协议中使用的特定语法。你只需要编写函数。
虽然这里有一个技术限制(协议不符合自身),即使 Swift 语法可以支持符合自身的协议(并且将来有办法),你仍然永远不应该以这种方式实现 Comparable。 Comparable 需要 Equatable。一个人永远不能等同于一辆汽车。那是因为 Equatable 需要的不仅仅是 ==
函数。它需要可替代性。如果两件事在 Equatable 意义上“相等”,那么系统可以总是 用一个代替另一个,你永远不会关心它给你哪个。人和车就不是这样了。
为避免此类问题,不建议在此处使用<
。这意味着这些东西只有一种合理的顺序,而“生日”并不是这些东西的唯一顺序。因此,如果您想比较日期,我肯定会建议您明确并比较日期。
感谢@Rob Napier 的精彩回答。
我想补充一些东西 - 对于那些想要符合 Comparable
以便能够对数组进行排序的人,我写了这个扩展:
extension Array where Element: Birthday {
mutating func sort() {
sort(by: { [=10=].date < .date })
}
func sorted() -> [Element] {
return sorted(by: { [=10=].date < .date })
}
}
大家新年快乐
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
我该怎么做?非常感谢
您可以>
轻松完成。只需编写以下顶层函数:
func > (lhs: Birthday, rhs: Birthday) -> Bool { lhs.date > rhs.date }
但是你不能让 Birthday 符合 Comparable。 Comparable 要求类型实现以下内容:
static func < (lhs: Self, rhs: Self) -> Bool
Self
是符合协议的类型。协议不符合自身。它们不是“类型”。他们描述类型。 (在某些情况下,可能会生成隐式存在类型,但存在类型不能在 Swift 中进行操作。)要具有可比性,一个类型必须能够将自己与另一个 相同的事物进行比较输入,你无法通过协议获得它。
但是您可以创建任何您希望在协议中使用的特定语法。你只需要编写函数。
虽然这里有一个技术限制(协议不符合自身),即使 Swift 语法可以支持符合自身的协议(并且将来有办法),你仍然永远不应该以这种方式实现 Comparable。 Comparable 需要 Equatable。一个人永远不能等同于一辆汽车。那是因为 Equatable 需要的不仅仅是 ==
函数。它需要可替代性。如果两件事在 Equatable 意义上“相等”,那么系统可以总是 用一个代替另一个,你永远不会关心它给你哪个。人和车就不是这样了。
为避免此类问题,不建议在此处使用<
。这意味着这些东西只有一种合理的顺序,而“生日”并不是这些东西的唯一顺序。因此,如果您想比较日期,我肯定会建议您明确并比较日期。
感谢@Rob Napier 的精彩回答。
我想补充一些东西 - 对于那些想要符合 Comparable
以便能够对数组进行排序的人,我写了这个扩展:
extension Array where Element: Birthday {
mutating func sort() {
sort(by: { [=10=].date < .date })
}
func sorted() -> [Element] {
return sorted(by: { [=10=].date < .date })
}
}