这很难用语言表达,但我创建了一个最小的示例。
这里有一个要点,如果您愿意... https://gist.github.com/anonymous/67d83fb2f286cf84539b58be96a971d3
“数据项”协议(protocol)
我有一个协议(protocol),它定义了具有属性 number
的 Sortable
对象。
protocol Sortable: Comparable {
var number: Int {get}
static func < (lhs:Self, rhs: Self) -> Bool
static func == (lhs:Self, rhs: Self) -> Bool
}
struct BasicSortable: Sortable {
let number: Int
static func < (lhs:BasicSortable, rhs: BasicSortable) -> Bool {
return lhs.number < rhs.number
}
static func == (lhs:BasicSortable, rhs: BasicSortable) -> Bool {
return lhs.number == rhs.number
}
}
“ worker ”协议(protocol)
然后我有一个协议(protocol)可以对这些 Sortable
类型做一些事情。但是因为它有一个 Self 要求,它需要被定义为一个具有关联类型的协议(protocol),并在结构中作为通用属性...
protocol Sorter {
associatedtype Item: Sortable
func sort(items: [Item]) -> [Item]
}
// Two different sorters
struct AscendingSorter<T:Sortable>: Sorter {
typealias Item = T
func sort(items: [T]) -> [T] {
return items.sorted()
}
}
struct DescendingSorter<T:Sortable>: Sorter {
typealias Item = T
func sort(items: [T]) -> [T] {
return items.sorted{$0 > $1}
}
}
处理程序
最后是一个将所有内容组合在一起的结构......
struct DataHandler<T: Sortable> {
let items: [T]
let sortedItems: [T]
init(unsortedItems: [T]) {
items = unsortedItems
let sorter = AscendingSorter<T>()
sortedItems = sorter.sort(items: unsortedItems)
}
}
让一切正常运转
一切正常。
let array = [
BasicSortable(number: 1),
BasicSortable(number: 8),
BasicSortable(number: 13),
BasicSortable(number: 3),
BasicSortable(number: 4),
BasicSortable(number: 14),
BasicSortable(number: 5),
BasicSortable(number: 12),
BasicSortable(number: 3),
]
let handler = DataHandler(unsortedItems: array)
handler.sortedItems
这会根据我在 Handler 中创建的排序器类型以正确的顺序打印出项目数组
问题
我现在想做的是为这个 sorter
结构找到一个属性声明,它可以将任何 Sorter 类型放入其中,但到目前为止我所做的一切尝试都失败了。
有办法吗?
在我想要的结构中......
let sorter: SomeTypeHere
然后在初始化中将其设置为...
sorter = AscendingSorter()
但我尝试过的组合都没有奏效。
谢谢
最佳答案
您可以使用类型删除来实现您自己的 AnySorter
.
从上面的你自己的代码开始:
protocol Sortable: Comparable {
var number: Int {get}
/* as Hamish mentions in his answer:
< and == already blueprinted in Comparable and Equatable */
}
protocol Sorter {
associatedtype Item: Sortable
func sort(items: [Item]) -> [Item]
}
构造一个 AnySorter
:
struct AnySorter<Item: Sortable>: Sorter {
private let _sort: ([Item]) -> [Item]
init<S: Sorter where S.Item == Item>(_ sorter: S) {
_sort = sorter.sort
}
func sort(items: [Item]) -> [Item] {
return _sort(items)
}
}
你使用的,例如作为 DataHandler
中初始值设定项的参数:
struct DataHandler<T: Sortable> {
let items: [T]
let sortedItems: [T]
init(unsortedItems: [T], sorter: AnySorter<T>) {
items = unsortedItems
sortedItems = sorter.sort(items: unsortedItems)
}
}
您的处理程序现在可以与已删除的类型一起使用 AnySorter
适用于您的 Sortable
类型。例如,对于您在问题中提供的两个简单分类器:
struct AscendingSorter<T:Sortable>: Sorter {
typealias Item = T
func sort(items: [T]) -> [T] {
return items.sorted()
}
}
struct DescendingSorter<T:Sortable>: Sorter {
typealias Item = T
func sort(items: [T]) -> [T] {
return items.sorted{$0 > $1}
}
}
/* example usage */
extension Int: Sortable {
var number: Int { return self }
}
let arr = [1, 4, 2, 8, 3]
let dataHandlerDesc = DataHandler(unsortedItems: arr, sorter: AnySorter(DescendingSorter()))
print(dataHandlerDesc.sortedItems) // [8, 4, 3, 2, 1]
let dataHandlerAsc = DataHandler(unsortedItems: arr, sorter: AnySorter(AscendingSorter()))
print(dataHandlerAsc.sortedItems) // [1, 2, 3, 4, 8]
编辑添加以回答您的评论:
Is it possible to take the input parameter and store it in a property? Would I just use
AnySorter<T>
as the type of the property?
是的,您可以在 DataHandler
中保留属性(property)与类型 AnySorter
.例如,对于一个人为的例子,我们可以让 sortedItems
是一个使用 AnySorter
的计算属性对存储的项目列表进行排序的实例(当然,实际上我们不想为每次调用都重新排序,但仅针对此示例!):
struct DataHandler<T: Sortable> {
let items: [T]
var sortedItems: [T] { return sorter.sort(items: items) }
var sorter: AnySorter<T>
init(unsortedItems: [T], sorter: AnySorter<T>) {
items = unsortedItems
self.sorter = sorter
}
mutating func changeSorter(newSorter: AnySorter<T>) {
sorter = newSorter
}
}
/* example usage */
extension Int: Sortable {
var number: Int { return self }
}
let arr = [1, 4, 2, 8, 3]
var dataHandler = DataHandler(unsortedItems: arr, sorter: AnySorter(DescendingSorter()))
print(dataHandler.sortedItems) // [8, 4, 3, 2, 1]
dataHandler.changeSorter(newSorter: AnySorter(AscendingSorter()))
print(dataHandler.sortedItems) // [1, 2, 3, 4, 8]
关于ios - 符合通用协议(protocol)的结构类型,其关联类型也是协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39477873/