Обычно, когда люди добавляют это соответствие, они пытаются сделать что-то вроде сортировки [Foo]
или найти минимальное значение, но это не сработает, даже если вы могли бы создать этот массив, потому что Comparable требует, чтобы тип быть сопоставимым со своим собственным типом , а не с другими, соответствующими протоколу. Так, например, учитывая ваш array
, вы не можете использовать array.min()
для поиска минимального элемента, потому что Comparable не требует, чтобы Foo было сопоставимо с Foo, только то, что соответствует Foo, можно сравнить с
Вместо этого вам нужно расширить протокол, чтобы требовать, чтобы соответствующие типы могли сравнивать себя с любыми Foo:
protocol Foo: Comparable {
// ... existing requirements
func isEqual(to: Foo) -> Bool
func isLessThan(_: Foo) -> Bool
}
Учитывая это, вы можете создавать любые другие алгоритмы, которые вам нужны. Вы не можете использовать формы по умолчанию contains
или sorted
, но вы можете использовать эти функции в параметрах where
и by
.
Вы также можете сделать это немного лучше, предоставив некоторые реализации по умолчанию:
extension Foo where Self: Equatable {
func isEqual(to other: Foo) -> Bool {
guard let other = other as? Self else {
return false
}
return self == other
}
}
И аналогично для isLessThan
.
И если вам нужны такие вещи, как contains
, вы также можете предоставить помощников, если это удобно:
extension Sequence where Element == Foo {
func contains(_ element: Element) -> Bool {
return contains(where: { $0.isEqual(to: element) })
}
}
Если вам нужна более длинная версия этого обсуждения, см. Generi c Swift: это не должно причинить вреда . Эта конкретная тема возникает в 37:40.