如果你更喜欢……这是一个要点
“数据项”协议
我有一个协议,它定义了具有类似属性编号的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 }}
“工人”协议
然后我有一个协议,可以使用这些Sortable类型做一些事情.但由于它具有自我要求,因此需要将其定义为具有关联类型的协议,并在结构中定义为通用属性…
protocol Sorter { associatedtype Item: Sortable func sort(items: [Item]) -> [Item]}// Two different sortersstruct 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{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),]let handler = DataHandler(unsortedItems: array)handler.sortedItems
让一切顺利
这一切都有效.
let sorter: SomeTypeHere
这将根据我在处理程序中创建的分拣机类型以正确的顺序打印出项目数组
问题
我现在要做的是为这个排序器结构找到一个属性声明,可以将任何Sorter类型放入其中,但到目前为止我尝试过的所有内容都失败了.
有没有办法做到这一点?
在结构中,我想…
sorter = AscendingSorter()
然后在init设置它就像…
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) }}
构造AnySorter:
struct DataHandler<T: Sortable> { let items: [T] let sortedItems: [T] init(unsortedItems: [T],sorter: AnySorter<T>) { items = unsortedItems sortedItems = sorter.sort(items: unsortedItems) }}
您使用的例如作为DataHandler中初始值设定项的参数:
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{AnySorter<T>
> } }}/* 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,3,1]let dataHandlerAsc = DataHandler(unsortedItems: arr,sorter: AnySorter(AscendingSorter()))print(dataHandlerAsc.sortedItems) // [1,8]
您的处理程序现在可以与应用于Sortable类型的类型擦除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,3]var dataHandler = DataHandler(unsortedItems: arr,sorter: AnySorter(DescendingSorter()))print(dataHandler.sortedItems) // [8,1]dataHandler.changeSorter(newSorter: AnySorter(AscendingSorter()))print(dataHandler.sortedItems) // [1,8]
编辑附加内容以回答您的评论:
Is it possible to take the input parameter and store it in a property?
Would I just use as the type of the property?
是的,您可以使用AnySorter类型在DataHandler中保留属性.例如,对于一个人为的例子,我们可以让sortedItems成为一个计算属性,利用AnySorter实例对存储的项目列表进行排序(当然,实际上我们不希望对每个调用进行重新排序,但是仅适用于此示例!):
总结以上是内存溢出为你收集整理的ios – 符合通用协议的结构类型,其关联类型也是协议全部内容,希望文章能够帮你解决ios – 符合通用协议的结构类型,其关联类型也是协议所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)