Я знаю ограничения генериков в Swift и почему они существуют, поэтому это не вопрос о ошибках компилятора. Скорее, я иногда сталкиваюсь с ситуациями, которые кажутся так, как если бы они были возможны с некоторой комбинацией ресурсов, доступных в (например, дженериков, связанных типов/протоколов и т.д.), Но, похоже, не могут найти решение.
В этом примере я пытаюсь придумать замену Swifty для NSSortDescriptor (просто для удовольствия). Он отлично работает, когда у вас есть только один дескриптор, но, как это часто делается с версией NS, было бы неплохо создать массив SortDescriptors для сортировки по нескольким ключам.
В другом исследовании здесь используется Swift KeyPaths. Поскольку для них требуется тип значения, а для сравнения требуется значение Comparable, я столкнулся с трудностями в определении того, где/как определить типы, удовлетворяющие всем.
Итак, вопрос в том, возможно ли это? Вот одно из ближайших решений, которые я придумал, но, как вы можете видеть внизу, он не подходит при построении массива.
Опять же, я понимаю, почему это не работает, но мне любопытно, есть ли способ достичь желаемой функциональности.
struct Person {
let name : String
let age : Int
}
struct SortDescriptor<T, V:Comparable> {
let keyPath: KeyPath<T,V>
let ascending : Bool
init(_ keyPath: KeyPath<T,V>, ascending:Bool = true) {
self.keyPath = keyPath
self.ascending = ascending
}
func compare(obj:T, other:T) -> Bool {
let v1 = obj[keyPath: keyPath]
let v2 = other[keyPath: keyPath]
return ascending ? v1 < v2 : v2 < v1
}
}
let jim = Person(name: "Jim", age: 30)
let bob = Person(name: "Bob", age: 35)
let older = SortDescriptor(\Person.age).compare(obj: jim, other: bob) // true
// Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
var descriptors = [SortDescriptor(\Person.age), SortDescriptor(\Person.name)]