【发布时间】:2014-06-20 19:54:23
【问题描述】:
如何在 Swift 中使用 Comparable 协议?在声明中它说我必须实现三个操作 =。我把所有这些都放在课堂上,但它不起作用。我还需要拥有这三个吗?因为应该可以从一个单一的推断出所有这些。
【问题讨论】:
如何在 Swift 中使用 Comparable 协议?在声明中它说我必须实现三个操作 =。我把所有这些都放在课堂上,但它不起作用。我还需要拥有这三个吗?因为应该可以从一个单一的推断出所有这些。
【问题讨论】:
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
【讨论】:
func == (lhs: ClassA, rhs: ClassB) -> Bool 的操作来比较两个不同的类(从测试来看,它似乎只在指定的方向上工作,因此您还必须创建func == (lhs: ClassB, rhs: ClassA) -> Bool)。换句话说,Swift 编译器将(X == Y) 解释为==(X, Y) 而不是X.==(Y)
==。我只实现了<,并且仍然能够测试是否相等。重复使用 < 与交换参数是否只是聪明?
这是 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
【讨论】:
要实现 Swift 的Comparable 协议,您需要首先通过实现static func == (lhs: Self, rhs: Self) -> Bool 来符合Equatable 协议,然后为Comparable 实现唯一需要的函数static func < (lhs: Self, rhs: Self) -> 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
}
}
这可能更接近生产级代码。
【讨论】: